Reputation: 6188
I have a Swift optional type and I want to chain a transformation to it (map
) and eventually pass it to a closure that prints it.
I want avoid unwrapping (using !
) the optional type because I don't want to execute the closure unless we have something inside the optional.
In Scala we use foreach
as a map
that returns Unit.
val oi = Option(2)
oi.map(_+1).foreach(println)
In Swift I get only until the increment (and the conversion to string)
let oi:Int? = 1
let oiplus = oi.map({$0 + 1}).map({String($0)})
// now we have "2"
Now how do I give this to print()
only in the case the optional is not nil?
Upvotes: 3
Views: 434
Reputation: 299355
While I usually do not recommend using map
for side-effects, in this case I believe it's the cleanest Swift.
_ = oiplus.map{ print($0) }
There is now a SequenceType.forEach
method that is explicitly for this problem, but Optional
is not a SequenceType
. You could of course extend Optional
to add a forEach
-like method (I'd probably call it apply
in Swift).
It's worth noting that this just avoids the if-lit
, which is barely any longer:
if let o = oiplus { print(o) }
But it admittedly doesn't chain as nicely as:
_ = oi
.map { $0 + 1 }
.map { print($0) }
See also http://www.openradar.me/23247992, which is basically Gabriele's answer.
Upvotes: 2
Reputation: 108101
I would just map over it
let oi: Int? = 1
let oiplus = oi.map{ $0 + 1 }.map { String($0) }
oiplus.map { print($0) }
Arguably not nice to map for producing a side-effect, but there's no foreach
for Optional
in Swift.
This also produces an unused result
warning in Swift 2.
If the semantic (and the warning) bug you, you can always define your own foreach
for Optional
. It's pretty straightforward:
extension Optional {
func forEach(f: Wrapped -> Void) {
switch self {
case .None: ()
case let .Some(w): f(w)
}
}
}
and then
let oi: Int? = 1
let oiplus = oi.map{ $0 + 1 }.map { String($0) }
oiplus.forEach { print($0) }
which resembles scala as much as possible.
Upvotes: 5