Functional Snippet #9: Map for Optionals
We've already talked about the map
function for arrays in a previous snippet. In case you're not familiar with it, map
transforms an array into a new array with the same size by applying a transform function to each element. For example:
let urls: [NSURL] = [ /* a bunch of image URLs */ ]
let images: [NSImage?] = urls.map { NSImage(contentsOfURL: $0) }
However, map
can not only be defined for arrays. On a more abstract level, map
simply unwraps values from a container type, applies a transform, and wraps them again. For example, we can also define it for optionals (it's already in the standard library, but you could easily write it yourself):
func map<A, B>(x: A?, f: (A )-> B) -> B? {
if let x1 = x {
return f(x1)
}
return nil
}
Let's say we wanted to transform an optional URL into an optional NSImage
, similar to the above array example. One approach would be to use Swift's optional binding:
let url: NSURL? = NSURL(string: "image.jpg")
var image: NSImage?
if let url1 = url {
image = NSImage(contentsOfURL:url1)
}
By using map
we can solve this in a much more succinct way though:
let url: NSURL? = NSURL(string: "image.jpg")
let image = map(url) { NSImage(contentsOfURL: $0) }
map
can be defined on many types, including dictionaries, tuples, functions and your own types.