Now I couldn’t resist throwing my own two cents onto buzz around Swift language. Right now, we are on early stage of excitement, which means lots of tutorials, and emerging libraries and extensions, including a few ones which sometimes recreate features that already exist 🙂
Update: As of 4th August 2014, this article is obsolete. Swift language has been enhanced with ??
operator, which does the same.
1 2 |
<span style="color: #97bde7;"><span style="color: #75bdfa;">"123"</span><span style="color: #f5f5f5;">.</span><span style="color: #65bfdc;">toInt</span><span style="color: #f5f5f5;">() ?? </span><span style="color: #ffef5a;">0</span><span style="color: #757575;">// 123</span></span> <span style="color: #97bde7;"><span style="color: #75bdfa;">"foo"</span><span style="color: #f5f5f5;">.</span><span style="color: #65bfdc;">toInt</span><span style="color: #f5f5f5;">() ?? 0</span><span style="color: #757575;">// 0</span></span> |
I’ll leave remaining of the post for proof of that I was first 🙂
But to the point.
One of respectable Swift features are optionals. They are more important than many of you may think, so it is good to take closer look.
Optionals are wrapping value which may or may not be present. Consider an example: we have string which we want to convert to a number:
1 2 |
<span style="color: #f5f5f5;"><span style="color: #8ce46d;">var</span> maybeANumber = <span style="color: #75bdfa;">"456"</span></span> <span style="color: #f5f5f5;"><span style="color: #8ce46d;">var</span> asNumber = <span style="color: #95a6b0;">maybeANumber</span>.<span style="color: #65bfdc;">toInt</span>()</span> |
When typed in Playground, asNumber value is {Some 456}. If you really want a number, you need to unwrap it
1 |
asNumber<span style="color: #f5f5f5;">!</span> |
Forced unwrap operator, exclamation mark, will, however generate an error when input value is not a string. Eventually you end up with if-checking:
1 2 3 4 5 |
<span style="color: #f5f5f5;"><span style="color: #8ce46d;">if</span> <span style="color: #8ce46d;">let</span> actual = <span style="color: #95a6b0;">asNumber</span> {</span> <span style="color: #f5f5f5;"> actual</span> <span style="color: #f5f5f5;">} <span style="color: #8ce46d;">else</span> {</span> <span style="color: #f5f5f5;"> <span style="color: #ffef5a;">0</span></span> <span style="color: #f5f5f5;">}</span> |
Optional type implements LogicValue protocol, so any Optional variable can be used in conditional expression.
This is not satisfactory for me, though. If language is borrowing so many good parts from functional language like Scala, why not steal more? Scala’s Option type offers a number of methods, including getOrElse(default), which returns a wrapped value if it exists, or provided default otherwise.
There’s no such thing in Swift (yet). So that encouraged me to implement it by myself. Swift documentation is very high-level, with little to none specific of under-the-hood operation.
After fiddling with undocumented methods a came to my own implementation of .getOrElse() using extension:
1 2 3 4 5 6 7 8 9 |
<span style="color: #8ce46d;">extension <span style="color: #65bfdc;">Optional</span><span style="color: #f5f5f5;"> {</span></span> <span style="color: #f5f5f5;"> <span style="color: #8ce46d;">func</span> getOrElse(val:<span style="color: #dd8f47;">T</span>) -> <span style="color: #dd8f47;">T</span> {</span> <span style="color: #f5f5f5;"> <span style="color: #8ce46d;">if</span> <span style="color: #65bfdc;">getLogicValue</span>() {</span> <span style="color: #f5f5f5;"> <span style="color: #8ce46d;">return</span> <span style="color: #8ce46d;">self</span>!</span> <span style="color: #f5f5f5;"> } <span style="color: #8ce46d;">else</span> {</span> <span style="color: #f5f5f5;"> <span style="color: #8ce46d;">return</span> val</span> <span style="color: #f5f5f5;"> }</span> <span style="color: #f5f5f5;"> }</span> <span style="color: #f5f5f5;">}</span> |
You can find in in my GitHub gist. Now, instead of creating if on the very end of chained Optional calls, use nice and clean:
1 2 |
<span style="color: #97bde7;"><span style="color: #75bdfa;">"123"</span><span style="color: #f5f5f5;">.</span><span style="color: #65bfdc;">toInt</span><span style="color: #f5f5f5;">().</span>getOrElse<span style="color: #f5f5f5;">(</span><span style="color: #ffef5a;">0</span><span style="color: #f5f5f5;">) </span><span style="color: #757575;">// 123</span></span> <span style="color: #97bde7;"><span style="color: #75bdfa;">"foo"</span><span style="color: #f5f5f5;">.</span><span style="color: #65bfdc;">toInt</span><span style="color: #f5f5f5;">().</span>getOrElse<span style="color: #f5f5f5;">(</span><span style="color: #ffef5a;">0</span><span style="color: #f5f5f5;">) </span><span style="color: #757575;">// 0</span></span> |
I really hope to find such feature in Swift 1.1, otherwise it is a good start of functional extensions library for Swift.