4 ms·
Shameless little self promotion "Comparing Optionals and Null in Swift, Scala, Ceylon and Kotlin" http://codemonkeyism.com/comparing-optionals-and-null-in-swi
by _Codemonkeyism 9y ago
Shameless little self promotion
"Comparing Optionals and Null in Swift, Scala, Ceylon and Kotlin"
http://codemonkeyism.com/comparing-optionals-and-null-in-swift-scala-ceylon-and-kotlin/ http://codemonkeyism.com/comparing-optionals-and-null-in-swi...
Personally I like Monads better than the Kotlin solution. Best is probably the way Swift does it.
- trevor-e 9y agoIn Swift you can also reference the enum types directly, like `var h:String? = .some("Hello")`. You're also missing `??` for Swift's version of default values.
- greenhouse_gas 9y agoMy issue with Monads (and why I like kotlin and swift nullable types) is that it allows the compiler to infer nullability like the following code: fun f(a1: Int?, a2: Int?): Int { if (a1 == null || a2 == null) { return 0 } //now you can do something like return a1+a2 } In contrast, if it didn't, the code would look like: fn func1(q: Option<i32>, z: Option<i32>) -> i32 { if let Some(q_in) = q { if let Some(z_in) = z { return q_in + z_in } } return 0 } Note the deeply nested parenthesis.
- yiransheng 9y agoIn languages like Haskell and Scala that supports `do` / `for` comprehension sugar, this could be done without the nesting: fn :: Maybe Int -> Maybe Int -> Int fn q z = fromMaybe 0 $ do q_in <- q z_in <- z return (q_in + z_in)
- zenhack 9y agoOr just: fn (Just q) (Just z) = q + z fn _ _ = 0
- brabel 9y agoWouldn't this let me call `fn true false` or `fn "hi" 2`? Or the second declaration takes the inferred type of the arguments from the first one?
- andolanra 9y agoThis isn't two functions: it's actually one function defined by cases. You can think of it as equivalent to fn x y = case (x, y) of (Just q, Just z) -> q + z (_, _) -> 0 but the case becomes implicit in the repetition of the function name at the top level of indentation.
- dllthomas 9y ago> at the top level of indentation At the same level, really - it works in a let or a where as well.
- masklinn 9y agoSurely since you have monads you can just use the tools they give you? fn = liftM2 (+)
- zenhack 9y agoThat doesn't do quite the same thing; the original example gets rid of the Maybe, defaulting to 0.
- masklinn 9y ago> That doesn't do quite the same thing You're missing the point entirely. > the original example gets rid of the Maybe, defaulting to 0. http://hackage.haskell.org/package/base-4.10.1.0/docs/Data-Maybe.html#v:fromMaybe http://hackage.haskell.org/package/base-4.10.1.0/docs/Data-M...
- willtim 9y agoIn modern Haskell, we are more likely to use the Applicative instance for Maybe, e.g. fromMaybe 0 $ (+) <$> xm <*> ym
- adambard 9y agoIn Scala, you can use `for`, although I think your point remains valid for languages without any sort of monad support: def func1(q: Option[Int], z: Option[Int]): Int = { (for { qval <- q zval <- z } yield q + z).getOrElse(0) }
- charliesome 9y agoIn Rust you can also write: if let (Some(q_in), Some(z_in)) = (q, z) { q_in + z_in } else { 0 }
- modalduality 9y agoMost languages with monads have tools for working with them. In Haskell, for example, even without `liftM2` or `sequenceM`, you can simply do case (xm, ym) of (Just x, Just y) -> x + y _ -> 0
- quotemstr 9y agoOh, come on. Is yielding 0 there really the best approach? It's a copout. You want full referential transparency.
- masklinn 9y agoThat's got nothing to do with monads though, you can do that in Swift or Rust which have a monadic option type but don't actually have monads: match (xm, ym) { (Some(x), Some(y)) => x + y, _ => 0 }
- wizao 9y agoI know you have got a TON of replies demonstrating better ways to check if a value is null or not. I believe they are all missing the point. In a language with monads, Option's should not be part of the function signature unless it is important to the logic of that function. Your given example should look like: func1(a: i32, z: i32) -> i32 { return a + z } I know it's not 1 to 1, but the idea is there. You would then use a tiny bit of glue code to combine all the stuff you have to get what you want. For example, if you have 2 nullabes as parameters, you use liftM2; if you have 1 nullable, you use liftM; or perhaps you just want reduce a structure, so you reach for foldM. etc. If your monadic code has to constantly figure out what monad it is, you aren't buying yourself much and I could see why you don't find them valuable. And if the function explicitly needs an Option, then it must be important and must be taken into consideration by the caller. I just don't think they should force the caller to consider them where not needed. I wanted to mention I often see similar statements with almost the identical code comparison that you made. I believe it has to do with retraining oneself to think functionally instead of imperatively. I'm curious about your background. For good measure, here's another example in Haskell: func1 a b = fromMaybe 0 (liftM2 (+) a b) And an uglier, but fun, point-free version: func1 = (fromMaybe 0 .) . liftM2 (+) I believe real-world examples would hold up better because the glue code would only be where needed.
- tome 9y ago> Option's should not be part of the function signature unless it is important to the logic of that function. Yes! Absolutely. Very important observation. In fact in Haskell Maybe should not be part of the signature if you want to return Nothing whenever one of the arguments is Nothing. > And an uglier, but fun, point-free version Yikes, please don't! People might get the wrong idea about how good Haskell is written.
- _Codemonkeyism 9y agoAs those others wrote you would probably use for I wrote a little bit about how to work with the Future Monad in "A Little Guide on Using Futures for Web Developers' http://codemonkeyism.com/a-little-guide-on-using-futures-for-web-developers/ http://codemonkeyism.com/a-little-guide-on-using-futures-for...