This page is no longer maintained — Please continue to the home page at www.scala-lang.org

a little sugar for Option

26 replies
Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.

How often do you want to perform an action if an Option is defined, and
(possibly) some other action if it is not? Currently, you can do it like
this:

def f(v:Option[Int])
= v map { x => printf("="+x) } getOrElse printf("=?")

... and so ...

scala> f(Some(111))
=111

scala> f(None)
=?

The example is weak because the two actions are trivial for the sake of
clarity. In practice, you would probably use some other method to
implement the above task. However, if you use Option a lot, the general
pattern does occur frequently, and in non-trivial ways.

It occurs to me that two trivial convenience methods can make this much
more readable: in the Option class, alias 'map' to 'ifDefined', and
'getOrElse' to 'otherwise', and you get:

def f(v:Option[Int])
= v ifDefined { x => printf("="+x) } otherwise printf("=?")

If you are not interest in the fall-back action, you could instead use:

def g(v:Option[Int]) = v ifDefined { x => printf("="+x) }

(currently you could use 'foreach' for that)

Much nicer to my eyes. Plus I think for beginning Scala programmers, this
would make it clearer why Option is a useful construct. Thoughts?

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

It occurs a lot because every single use of Option can be reduced to a
use of map/getOrElse. This is called the catamorphism for Option.
I can be observed by plonking in the constructors Some and None to map
and getOrElse respectively to get an identity function:

option map Some getOrElse None // identity

Here is flatMap written using only map and getOrElse. Notice the
similarity to if you'd used pattern matching:

scala> def flatMap[A, B](o: Option[A], f: A => Option[B]) = o map f
getOrElse None
flatMap: [A,B](Option[A],(A) => Option[B])Option[B]

Here is filter in the same manner:

scala> def filter[A](o: Option[A], f: A => Boolean) = o map (x =>
if(f(x)) Some(x) else None) getOrElse None
filter: [A](Option[A],(A) => Boolean)Option[A]

I could go on and on. Perhaps a blog post is in order. You should try
implementing more Option methods using only map and getOrElse as an
exercise.

On the matter of writing equivalent functions with different names, I
offer no comment.

Sam Stainsby wrote:
> How often do you want to perform an action if an Option is defined, and
> (possibly) some other action if it is not? Currently, you can do it like
> this:
>
> def f(v:Option[Int])
> = v map { x => printf("="+x) } getOrElse printf("=?")
>
> ... and so ...
>
> scala> f(Some(111))
> =111
>
> scala> f(None)
> =?
>
> The example is weak because the two actions are trivial for the sake of
> clarity. In practice, you would probably use some other method to
> implement the above task. However, if you use Option a lot, the general
> pattern does occur frequently, and in non-trivial ways.
>
> It occurs to me that two trivial convenience methods can make this much
> more readable: in the Option class, alias 'map' to 'ifDefined', and
> 'getOrElse' to 'otherwise', and you get:
>
> def f(v:Option[Int])
> = v ifDefined { x => printf("="+x) } otherwise printf("=?")
>
> If you are not interest in the fall-back action, you could instead use:
>
> def g(v:Option[Int]) = v ifDefined { x => printf("="+x) }
>
> (currently you could use 'foreach' for that)
>
> Much nicer to my eyes. Plus I think for beginning Scala programmers, this
> would make it clearer why Option is a useful construct. Thoughts?
>
>
>

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

Tony Morris wrote:
> I can be observed by plonking in the constructors Some and None to map
> and getOrElse respectively to get an identity function:
>
*It can be observed, not I :)

Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Tue, 29 Sep 2009 10:23:10 +1000, Tony Morris wrote:

> It occurs a lot because every single use of Option can be reduced to a
> use of map/getOrElse. This is called the catamorphism for Option.

If so, then should we conclude that the other methods are added to make
the code that uses Option more succinct and readable, and to make the
Option class more understandable (and less like some unfathomable
calculus).

> On the matter of writing equivalent functions with different names, I
> offer no comment.

A shame, because this was probably a key issue.

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: a little sugar for Option

Sam Stainsby wrote:
> On Tue, 29 Sep 2009 10:23:10 +1000, Tony Morris wrote:
>
>
>> It occurs a lot because every single use of Option can be reduced to a
>> use of map/getOrElse. This is called the catamorphism for Option.
>>
>
> If so, then should we conclude that the other methods are added to make
> the code that uses Option more succinct and readable, and to make the
> Option class more understandable (and less like some unfathomable
> calculus).
>

Precisely. You wouldn't write (option map f getOrElse None) nor would
you pattern-match it. There is a specialised function for this: (option
flatMap f).
And so on.

>
>> On the matter of writing equivalent functions with different names, I
>> offer no comment.
>>
>
> A shame, because this was probably a key issue.
>
I stay out of these ones. I care far (far far) less about function names
than many others on the list.

Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Tue, 29 Sep 2009 10:44:35 +1000, Tony Morris wrote:

> Sam Stainsby wrote:
>> On Tue, 29 Sep 2009 10:23:10 +1000, Tony Morris wrote:
>>> It occurs a lot because every single use of Option can be reduced to a
>>> use of map/getOrElse. This is called the catamorphism for Option.
>>>
>>>
>> If so, then should we conclude that the other methods are added to make
>> the code that uses Option more succinct and readable, and to make the
>> Option class more understandable (and less like some unfathomable
>> calculus).
>>
> Precisely. You wouldn't write (option map f getOrElse None) nor would
> you pattern-match it. There is a specialised function for this: (option
> flatMap f).
> And so on.

Good, so on that basis, my changes would make the code that uses Option
more readable, and make the Option class more understandable, which was
my original point. Or is there already some way to write { option map f
getOrElse g } (where f, g and are two general functions) that is clearer
than { option ifDefined f otherwise g } ?

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: a little sugar for Option

Sam Stainsby wrote:
> On Tue, 29 Sep 2009 10:44:35 +1000, Tony Morris wrote:
>
>
>> Sam Stainsby wrote:
>>
>>> On Tue, 29 Sep 2009 10:23:10 +1000, Tony Morris wrote:
>>>
>>>> It occurs a lot because every single use of Option can be reduced to a
>>>> use of map/getOrElse. This is called the catamorphism for Option.
>>>>
>>>>
>>>>
>>> If so, then should we conclude that the other methods are added to make
>>> the code that uses Option more succinct and readable, and to make the
>>> Option class more understandable (and less like some unfathomable
>>> calculus).
>>>
>>>
>> Precisely. You wouldn't write (option map f getOrElse None) nor would
>> you pattern-match it. There is a specialised function for this: (option
>> flatMap f).
>> And so on.
>>
>
> Good, so on that basis, my changes would make the code that uses Option
> more readable, and make the Option class more understandable, which was
> my original point. Or is there already some way to write { option map f
> getOrElse g } (where f, g and are two general functions) that is clearer
> than { option ifDefined f otherwise g } ?
>
>
>
You don't write (option flatMap f) because it has less characters than
the alternatives. The point is that flatMap has already applied part of
the computation since it is specialised to some extent. Notice that you
cannot write both map and getOrElse using only flatMap (though with Some
you can write map). Using map and getOrElse offers nothing
computationally above pattern matching and there is no measurable reason
to choose one over the other (performance aside).

If you are using map and getOrElse and there doesn't exist a function
that specialises part of your computation, then I recommend either
pattern-matching or writing such a function that does partially specialise.

Providing primarily syntactic appeasement is not my game. I'm sure
others would love to join in on it, but not me.

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: a little sugar for Option

Hi Sam,

Your suggestion I think is more readable than the map/getOrElse
version, especially to the uninitiated. I however usually use a
pattern match like this:

scala> def f(v: Option[Int]) {
| v match {
| case Some(x) => printf("=" + x)
| case None => printf("=?")
| }
| }
f: (Option[Int])Unit

scala> f(Some(111))
=111
scala> f(None)
=?

Another way to do this is like this:

scala> def f(v: Option[Int]) {
| if (v.isDefined) printf("=" + v.get) else printf("=?")
| }
f: (Option[Int])Unit

scala> f(Some(111))
=111

scala> f(None)
=?

This latter one doesn't look too much different than your suggestion.
Also, if you prefer your syntax you can have it with an implicit
conversion on Option, but I would be inclined to stick with one of the
standard approaches.

Bill

On Mon, Sep 28, 2009 at 5:14 PM, Sam Stainsby
wrote:
> How often do you want to perform an action if an Option is defined, and
> (possibly) some other action if it is not? Currently, you can do it like
> this:
>
> def f(v:Option[Int])
>  = v map { x => printf("="+x) } getOrElse printf("=?")
>
>  ... and so ...
>
> scala> f(Some(111))
> =111
>
> scala> f(None)
> =?
>
> The example is weak because the two actions are trivial for the sake of
> clarity. In practice, you would probably use some other method to
> implement the above task. However, if you use Option a lot, the general
> pattern does occur frequently, and in non-trivial ways.
>
> It occurs to me that two trivial convenience methods can make this much
> more readable: in the Option class, alias 'map' to 'ifDefined', and
> 'getOrElse' to 'otherwise', and you get:
>
> def f(v:Option[Int])
>  = v ifDefined { x => printf("="+x) } otherwise printf("=?")
>
> If you are not interest in the fall-back action, you could instead use:
>
> def g(v:Option[Int]) = v ifDefined { x => printf("="+x) }
>
> (currently you could use 'foreach' for that)
>
> Much nicer to my eyes. Plus I think for beginning Scala programmers, this
> would make it clearer why Option is a useful construct. Thoughts?
>
>

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

Bill Venners wrote:
> Hi Sam,
>
> Your suggestion I think is more readable than the map/getOrElse
> version, especially to the uninitiated. I however usually use a
> pattern match like this:
>
> scala> def f(v: Option[Int]) {
> | v match {
> | case Some(x) => printf("=" + x)
> | case None => printf("=?")
> | }
> | }
> f: (Option[Int])Unit
>
> scala> f(Some(111))
> =111
> scala> f(None)
> =?
>

Prefer:

def f(v: Option[Int]) { printf(v match {
case Some(x) => "=" + x
case None => "=?"
}
}

> Another way to do this is like this:
>
> scala> def f(v: Option[Int]) {
> | if (v.isDefined) printf("=" + v.get) else printf("=?")
> | }
> f: (Option[Int])Unit
>
> scala> f(Some(111))
> =111
>
> scala> f(None)
> =?
>

Prefer:

def f(v: Option[Int]) {
printf(if(v.isDefined) "=" + v.get else "=?")
}

Side-effects to the outside :)

Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Mon, 28 Sep 2009 19:03:59 -0700, Bill Venners wrote:

> scala> def f(v: Option[Int]) {
> | v match {
> | case Some(x) => printf("=" + x)
> | case None => printf("=?")
> | }
> | }

Yes, for lack of an alternative, I use this because it is clearer.
However it is more verbose. This is what Tony was referring to as well I
think.

> scala> def f(v: Option[Int]) {
> | if (v.isDefined) printf("=" + v.get) else printf("=?") | }

This is not much better than the old Java idiom:

if (v != null) the { do something with v } else {do something else}

which is what we want to avoid because they both lead to the possibility
of accidental runtime exceptions in non-trivial code,
NoSuchElementException in the former case and NPE in the latter, that are
not detected at compile time.

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: a little sugar for Option

Hi Tony,

Yes, I prefer that too and that's how I do it in my code. I was just
translating Sam's example to illustrate the difference.

Bill

On Mon, Sep 28, 2009 at 7:13 PM, Tony Morris wrote:
>
>
> Bill Venners wrote:
>> Hi Sam,
>>
>> Your suggestion I think is more readable than the map/getOrElse
>> version, especially to the uninitiated. I however usually use a
>> pattern match like this:
>>
>> scala> def f(v: Option[Int]) {
>>      |   v match {
>>      |     case Some(x) => printf("=" + x)
>>      |     case None => printf("=?")
>>      |   }
>>      | }
>> f: (Option[Int])Unit
>>
>> scala> f(Some(111))
>> =111
>> scala> f(None)
>> =?
>>
>
> Prefer:
>
> def f(v: Option[Int]) { printf(v match {
>    case Some(x) => "=" + x
>    case None => "=?"
>  }
> }
>
>> Another way to do this is like this:
>>
>> scala> def f(v: Option[Int]) {
>>      |   if (v.isDefined) printf("=" + v.get) else printf("=?")
>>      | }
>> f: (Option[Int])Unit
>>
>> scala> f(Some(111))
>> =111
>>
>> scala> f(None)
>> =?
>>
>
> Prefer:
>
> def f(v: Option[Int]) {
>  printf(if(v.isDefined) "=" + v.get else "=?")
> }
>
>
> Side-effects to the outside :)
>
> --
> Tony Morris
> http://tmorris.net/
>
>
>

Grey
Joined: 2009-01-03,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option
At first blush the namings of some of Options methods seem a bit tortured.  Why did they use such non-intuitive names such as "map"  and "flatmap" for god-sakes ... etc.  But there is sound method behind the apparent madness.  

Search for some blog posts of using Option with for-comprehensions.
http://debasishg.blogspot.com/2008/03/monads-another-way-to-abstract.html

Now why they used map and flatmap is apparent.  But its even deeper than just "you can use Option inside of for-comprehensions".   Consider flatmap as Monadic bind, map as the unit function, yield as return, and one sees that for-comprehensions are truly _not_ syntactic sugar for iterative loops or Pythonic like-generators,  and Option has some deeper fundamental aspect then just a binary algebraic type and the whole thing is weaved together via a deeper structure.

However as in your example, map and flatmap can look a bit tortured in some use cases until you get comfortable with them.  But, as you have pointed out, it is a triviality to just alias them, as you did.  

Rename "map" and the above structure falls apart; it must remain.  If you were to formally add the "ifDefined" alias to Option than we face the "why are there two identical methods in Option, "map" and "ifDefined", one of them is redundant question."  

On Mon, Sep 28, 2009 at 8:14 PM, Sam Stainsby <sam [at] sustainablesoftware [dot] com [dot] au> wrote:
How often do you want to perform an action if an Option is defined, and
(possibly) some other action if it is not? Currently, you can do it like
this:

def f(v:Option[Int])
 = v map { x => printf("="+x) } getOrElse printf("=?")

 ... and so ...

scala> f(Some(111))
=111

scala> f(None)
=?

The example is weak because the two actions are trivial for the sake of
clarity. In practice, you would probably use some other method to
implement the above task. However, if you use Option a lot, the general
pattern does occur frequently, and in non-trivial ways.

It occurs to me that two trivial convenience methods can make this much
more readable: in the Option class, alias 'map' to 'ifDefined', and
'getOrElse' to 'otherwise', and you get:

def f(v:Option[Int])
 = v ifDefined { x => printf("="+x) } otherwise printf("=?")

If you are not interest in the fall-back action, you could instead use:

def g(v:Option[Int]) = v ifDefined { x => printf("="+x) }

(currently you could use 'foreach' for that)

Much nicer to my eyes. Plus I think for beginning Scala programmers, this
would make it clearer why Option is a useful construct. Thoughts?


Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

The term map comes from category theory.
http://en.wikipedia.org/wiki/Functor
"A functor F from C to D is a mapping that..."

The term flatMap comes from the composition of map then a flatten operation.
Loosely, flatMap is equivalent to ((flatten compose _) compose map) for
any monadic type constructor such as Option.

However, I don't believe that Option has a flatten method in its object
in the Scala libraries, but List does:
(list flatMap f) is equivalent to List.flatten(list map f)
for any values of list and f (try it!).

flatten is also sometimes known as join and the signature is M[M[A]] =>
M[A].

Ray Racine wrote:
> At first blush the namings of some of Options methods seem a bit
> tortured. Why did they use such non-intuitive names such as "map"
> and "flatmap" for god-sakes ... etc. But there is sound method behind
> the apparent madness.
>
> Search for some blog posts of using Option with for-comprehensions.
> http://debasishg.blogspot.com/2008/03/monads-another-way-to-abstract.html
>
> Now why they used map and flatmap is apparent. But its even deeper
> than just "you can use Option inside of for-comprehensions".
> Consider flatmap as Monadic bind, map as the unit function, yield as
> return, and one sees that for-comprehensions are truly _not_ syntactic
> sugar for iterative loops or Pythonic like-generators, and Option has
> some deeper fundamental aspect then just a binary algebraic type and
> the whole thing is weaved together via a deeper structure.
>
> However as in your example, map and flatmap can look a bit tortured in
> some use cases until you get comfortable with them. But, as you have
> pointed out, it is a triviality to just alias them, as you did.
>
> Rename "map" and the above structure falls apart; it must remain. If
> you were to formally add the "ifDefined" alias to Option than we face
> the "why are there two identical methods in Option, "map" and
> "ifDefined", one of them is redundant question."
>
> On Mon, Sep 28, 2009 at 8:14 PM, Sam Stainsby
> > wrote:
>
> How often do you want to perform an action if an Option is
> defined, and
> (possibly) some other action if it is not? Currently, you can do
> it like
> this:
>
> def f(v:Option[Int])
> = v map { x => printf("="+x) } getOrElse printf("=?")
>
> ... and so ...
>
> scala> f(Some(111))
> =111
>
> scala> f(None)
> =?
>
> The example is weak because the two actions are trivial for the
> sake of
> clarity. In practice, you would probably use some other method to
> implement the above task. However, if you use Option a lot, the
> general
> pattern does occur frequently, and in non-trivial ways.
>
> It occurs to me that two trivial convenience methods can make this
> much
> more readable: in the Option class, alias 'map' to 'ifDefined', and
> 'getOrElse' to 'otherwise', and you get:
>
> def f(v:Option[Int])
> = v ifDefined { x => printf("="+x) } otherwise printf("=?")
>
> If you are not interest in the fall-back action, you could instead
> use:
>
> def g(v:Option[Int]) = v ifDefined { x => printf("="+x) }
>
> (currently you could use 'foreach' for that)
>
> Much nicer to my eyes. Plus I think for beginning Scala
> programmers, this
> would make it clearer why Option is a useful construct. Thoughts?
>
>

Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Tue, 29 Sep 2009 08:21:51 -0400, Ray Racine wrote:

> If you were to formally add the "ifDefined" alias to Option than we face
> the "why are there two identical methods in Option, "map" and
> "ifDefined", one of them is redundant question."

.. because it would make a whole lot of code much easier to read for an
extremely cheap/safe cheap code addition, and would make the language
more comprehensible to non-FP types. Such methods do occur elsewhere in
the scala code base such as ifDefinedAt in scala.collection.Map. I don't
think it needs to be a taboo subject :-)

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Re: a little sugar for Option
I don't think it's the best practice to use map and getOrElse a lot with Option.  It certainly works, and it's a very elegant abstraction as Tony has described.  But there's a problem with option:

scala> val a:Option[Int] = null
scala> a map { i => println(i) } getOrElse { println("Undefined") }
java.lang.NullPointerException
    at .<init>(<console>:9)
    . . .

Oops!  We could bemoan the sorry state of null objects in Java spoiling our pristine Scala Options, or we could

scala> a match { case Some(i) => println(i) ; case _ => println("Undefined") }
Undefined

Thus, if you're not sure whether your Option is from a function obeying the sensible contract (i.e. always return Some(Something) or None), your code will still work as intended.

Then there's the nifty for-as-a-check construct:

scala> val a = Some(5)
scala> val b = Some(" Hi! ")
scala> val c = Some((false,true))
scala> for (i<-a ; j<-b ; k<-c) { println(i + j + k) }
5 Hi! (false,true)

which substitutes for some of the other uses of map.

Since match and for cover some of the most interesting use cases for map/getOrElse (sometimes better than map/getOrElse does), and since it is not *that* hard to learn that an option is a collection (of zero or one elements) and can be used accordingly, I don't see a compelling argument to add aliases to the syntax.

And, incidentally, I think the map/getOrElse version requires an extra object creation (the Option[Unit] from map); if one were going to do this a lot one would probably prefer

opt.doOrElse(i=>println(i))(println("Undefined"))

where

def doOrElse[T,U](f: T=>U)(g: =>U) { this match { case Some(x) => f(x) ; case _ => g } }

which might work even better taking the class as the first argument so you could catch the null case:

def useOrElse[T,U](o:Option[T])(f: T=>U)(g: =>U) {
  o match { case Some(x) => f(x) ; case _ => g }
}

useOrElse(opt)(i=>println(i))(println("Undefined"))

  --Rex


On Tue, Sep 29, 2009 at 9:32 AM, Sam Stainsby <sam [at] sustainablesoftware [dot] com [dot] au> wrote:
On Tue, 29 Sep 2009 08:21:51 -0400, Ray Racine wrote:

> If you were to formally add the "ifDefined" alias to Option than we face
> the "why are there two identical methods in Option, "map" and
> "ifDefined", one of them is redundant question."

.. because it would make a whole lot of code much easier to read for an
extremely cheap/safe cheap code addition, and would make the language
more comprehensible to non-FP types. Such methods do occur elsewhere in
the scala code base such as ifDefinedAt in scala.collection.Map. I don't
think it needs to be a taboo subject :-)


Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: Re: a little sugar for Option

Or just stop using null.

2009/9/29 Rex Kerr :
> I don't think it's the best practice to use map and getOrElse a lot with
> Option.  It certainly works, and it's a very elegant abstraction as Tony has
> described.  But there's a problem with option:
>
> scala> val a:Option[Int] = null
> scala> a map { i => println(i) } getOrElse { println("Undefined") }
> java.lang.NullPointerException
>     at .(:9)
>     . . .
>
> Oops!  We could bemoan the sorry state of null objects in Java spoiling our
> pristine Scala Options, or we could
>
> scala> a match { case Some(i) => println(i) ; case _ => println("Undefined")
> }
> Undefined
>
> Thus, if you're not sure whether your Option is from a function obeying the
> sensible contract (i.e. always return Some(Something) or None), your code
> will still work as intended.
>
> Then there's the nifty for-as-a-check construct:
>
> scala> val a = Some(5)
> scala> val b = Some(" Hi! ")
> scala> val c = Some((false,true))
> scala> for (i<-a ; j<-b ; k<-c) { println(i + j + k) }
> 5 Hi! (false,true)
>
> which substitutes for some of the other uses of map.
>
> Since match and for cover some of the most interesting use cases for
> map/getOrElse (sometimes better than map/getOrElse does), and since it is
> not *that* hard to learn that an option is a collection (of zero or one
> elements) and can be used accordingly, I don't see a compelling argument to
> add aliases to the syntax.
>
> And, incidentally, I think the map/getOrElse version requires an extra
> object creation (the Option[Unit] from map); if one were going to do this a
> lot one would probably prefer
>
> opt.doOrElse(i=>println(i))(println("Undefined"))
>
> where
>
> def doOrElse[T,U](f: T=>U)(g: =>U) { this match { case Some(x) => f(x) ;
> case _ => g } }
>
> which might work even better taking the class as the first argument so you
> could catch the null case:
>
> def useOrElse[T,U](o:Option[T])(f: T=>U)(g: =>U) {
>   o match { case Some(x) => f(x) ; case _ => g }
> }
>
> useOrElse(opt)(i=>println(i))(println("Undefined"))
>
>   --Rex
>
>
> On Tue, Sep 29, 2009 at 9:32 AM, Sam Stainsby
> wrote:
>>
>> On Tue, 29 Sep 2009 08:21:51 -0400, Ray Racine wrote:
>>
>> > If you were to formally add the "ifDefined" alias to Option than we face
>> > the "why are there two identical methods in Option, "map" and
>> > "ifDefined", one of them is redundant question."
>>
>> .. because it would make a whole lot of code much easier to read for an
>> extremely cheap/safe cheap code addition, and would make the language
>> more comprehensible to non-FP types. Such methods do occur elsewhere in
>> the scala code base such as ifDefinedAt in scala.collection.Map. I don't
>> think it needs to be a taboo subject :-)
>>
>
>

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: Re: a little sugar for Option

Hi Sam,

I think you suggested a nice syntax and thinking about it a bit more I
think it might make a nice addition to Option. I agree it is good to
avoid redundancy, but Option is so commonly used that it may be
justified because this is more concise than the pattern match I use
and more readable than map and getOrElse. For still more redundancy
you could also have an ifEmpty in there for symmetry:

v ifDefined { x => printf("="+x) } otherwise printf("=?")
v ifEmpty printf("=?") otherwise { x => printf("="+x) }

Bill

On Tue, Sep 29, 2009 at 6:32 AM, Sam Stainsby
wrote:
> On Tue, 29 Sep 2009 08:21:51 -0400, Ray Racine wrote:
>
>> If you were to formally add the "ifDefined" alias to Option than we face
>> the "why are there two identical methods in Option, "map" and
>> "ifDefined", one of them is redundant question."
>
> .. because it would make a whole lot of code much easier to read for an
> extremely cheap/safe cheap code addition, and would make the language
> more comprehensible to non-FP types. Such methods do occur elsewhere in
> the scala code base such as ifDefinedAt in scala.collection.Map. I don't
> think it needs to be a taboo subject :-)
>
>

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Re: a little sugar for Option


On Tue, Sep 29, 2009 at 8:53 PM, Bill Venners <bill [at] artima [dot] com> wrote:
Hi Sam,

I think you suggested a nice syntax and thinking about it a bit more I
think it might make a nice addition to Option. I agree it is good to
avoid redundancy, but Option is so commonly used that it may be
justified because this is more concise than the pattern match I use
and more readable than map and getOrElse. For still more redundancy
you could also have an ifEmpty in there for symmetry:

v ifDefined { x => printf("="+x) } otherwise printf("=?")
v ifEmpty printf("=?") otherwise { x => printf("="+x) }

If that's the road you want to go,
Why not:

v ifSome { x => printf("="+x) } otherwise printf("=?")
v ifNone printf("=?") otherwise { x => printf("="+x) }
 

Bill

On Tue, Sep 29, 2009 at 6:32 AM, Sam Stainsby
<sam [at] sustainablesoftware [dot] com [dot] au> wrote:
> On Tue, 29 Sep 2009 08:21:51 -0400, Ray Racine wrote:
>
>> If you were to formally add the "ifDefined" alias to Option than we face
>> the "why are there two identical methods in Option, "map" and
>> "ifDefined", one of them is redundant question."
>
> .. because it would make a whole lot of code much easier to read for an
> extremely cheap/safe cheap code addition, and would make the language
> more comprehensible to non-FP types. Such methods do occur elsewhere in
> the scala code base such as ifDefinedAt in scala.collection.Map. I don't
> think it needs to be a taboo subject :-)
>
>



--
Bill Venners
Artima, Inc.
http://www.artima.com



--
Viktor Klang

Blog: klangism.blogspot.com
Twttr: viktorklang

Lift Committer - liftweb.com
AKKA Committer - akkasource.org
Cassidy - github.com/viktorklang/Cassidy.git
SoftPub founder: http://groups.google.com/group/softpub
loverdos
Joined: 2008-11-18,
User offline. Last seen 2 years 27 weeks ago.
Re: Re: a little sugar for Option
Oh, I liked that :)
On Sep 29, 2009, at 22:15, Viktor Klang wrote:


On Tue, Sep 29, 2009 at 8:53 PM, Bill Venners <bill [at] artima [dot] com> wrote:
Hi Sam,

I think you suggested a nice syntax and thinking about it a bit more I
think it might make a nice addition to Option. I agree it is good to
avoid redundancy, but Option is so commonly used that it may be
justified because this is more concise than the pattern match I use
and more readable than map and getOrElse. For still more redundancy
you could also have an ifEmpty in there for symmetry:

v ifDefined { x => printf("="+x) } otherwise printf("=?")
v ifEmpty printf("=?") otherwise { x => printf("="+x) }

If that's the road you want to go,
Why not:

v ifSome { x => printf("="+x) } otherwise printf("=?")
v ifNone printf("=?") otherwise { x => printf("="+x) }
 

Bill

On Tue, Sep 29, 2009 at 6:32 AM, Sam Stainsby
<sam [at] sustainablesoftware [dot] com [dot] au> wrote:
> On Tue, 29 Sep 2009 08:21:51 -0400, Ray Racine wrote:
>
>> If you were to formally add the "ifDefined" alias to Option than we face
>> the "why are there two identical methods in Option, "map" and
>> "ifDefined", one of them is redundant question."
>
> .. because it would make a whole lot of code much easier to read for an
> extremely cheap/safe cheap code addition, and would make the language
> more comprehensible to non-FP types. Such methods do occur elsewhere in
> the scala code base such as ifDefinedAt in scala.collection.Map. I don't
> think it needs to be a taboo subject :-)
>
>



--
Bill Venners
Artima, Inc.
http://www.artima.com



--
Viktor Klang

Blog: klangism.blogspot.com
Twttr: viktorklang

Lift Committer - liftweb.com
AKKA Committer - akkasource.org
Cassidy - github.com/viktorklang/Cassidy.git
SoftPub founder: http://groups.google.com/group/softpub

-- 
   __~O
  -\ <,       Christos KK Loverdos
(*)/ (*)      http://ckkloverdos.com





Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Tue, 29 Sep 2009 21:15:02 +0200, Viktor Klang wrote:

>> v ifDefined { x => printf("="+x) } otherwise printf("=?") v ifEmpty
>> printf("=?") otherwise { x => printf("="+x) }
>>
>>
> If that's the road you want to go,
> Why not:
>
> v ifSome { x => printf("="+x) } otherwise printf("=?")
> v ifNone printf("=?") otherwise { x => printf("="+x) }

I chose my naming because of the symmetry: isDefined to ifDefined
and now as Bill suggested there is: isEmpty to ifEmpty
but I can appreciate your way as well. I wonder then if Option should
have originally had isSome & isNone rather than isDefined & isEmpty ...
but too late for that I think.

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: Re: a little sugar for Option

Hi All,

Either one would work. ifSome/ifNone is probably a bit clearer. It is
less consistent with isDefined and isEmpty, but maybe that's a good
thing because when you see ifDefined, you'd have to look carefully to
make sure it isn't isDefined.

Of course people could add such sugar themselves in their own project,
so it doesn't have to be on Option. But I sure do that pattern match a
lot of times. Might be worth some sugar on Option someday, but it
might also be good to let people get some experience using variations
of such sugar before plopping sweetener like this onto such a central
and important library type. Though another thing I try and avoid is
adding implicit conversions to make things more "readable" like this,
because in so doing, I also make it less standard (which makes it
harder to read in that way).

Bill

On Tue, Sep 29, 2009 at 2:40 PM, Sam Stainsby
wrote:
> On Tue, 29 Sep 2009 21:15:02 +0200, Viktor Klang wrote:
>
>>> v ifDefined { x => printf("="+x) } otherwise printf("=?") v ifEmpty
>>> printf("=?") otherwise { x => printf("="+x) }
>>>
>>>
>> If that's the road you want to go,
>> Why not:
>>
>> v ifSome { x => printf("="+x) } otherwise printf("=?")
>> v ifNone printf("=?") otherwise { x => printf("="+x) }
>
> I chose my naming because of the symmetry: isDefined to ifDefined
> and now as Bill suggested there is: isEmpty to ifEmpty
> but I can appreciate your way as well. I wonder then if Option should
> have originally had isSome & isNone rather than isDefined & isEmpty ...
> but too late for that I think.
>
>

Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Tue, 29 Sep 2009 20:03:15 -0700, Bill Venners wrote:

> Either one would work. ifSome/ifNone is probably a bit clearer. It is
> less consistent with isDefined and isEmpty, but maybe that's a good
> thing because when you see ifDefined, you'd have to look carefully to
> make sure it isn't isDefined.
>
> Of course people could add such sugar themselves in their own project,
> so it doesn't have to be on Option. But I sure do that pattern match a
> lot of times. Might be worth some sugar on Option someday, but it might
> also be good to let people get some experience using variations of such
> sugar before plopping sweetener like this onto such a central and
> important library type. Though another thing I try and avoid is adding
> implicit conversions to make things more "readable" like this, because
> in so doing, I also make it less standard (which makes it harder to read
> in that way).

Good points, all of them. I'm not sure what the best strategy is for
people getting some experience with it, other than annotating it
'experimental'.

Another idea I'm going to play with is whether Option[T] could inherit
from Seq[T] (or whatever it is in scala 2.8 now). Methods like 'map',
'foreach', 'filter', 'size', etc. I think will be compatible, and maybe
even sensible. Whether others are remains to be seen ...

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: Re: a little sugar for Option

Hi Sam,

By experience I meant implementing it with an implicit in your own
code and using it for a while. See how it goes that way. With
experience you may decide you clearly like ifSome over ifDefined, or
decide that it wasn't such a good idea after all and you'd rather just
use a pattern match, etc.

Bill

On Tue, Sep 29, 2009 at 8:17 PM, Sam Stainsby
wrote:
> On Tue, 29 Sep 2009 20:03:15 -0700, Bill Venners wrote:
>
>> Either one would work. ifSome/ifNone is probably a bit clearer. It is
>> less consistent with isDefined and isEmpty, but maybe that's a good
>> thing because when you see ifDefined, you'd have to look carefully to
>> make sure it isn't isDefined.
>>
>> Of course people could add such sugar themselves in their own project,
>> so it doesn't have to be on Option. But I sure do that pattern match a
>> lot of times. Might be worth some sugar on Option someday, but it might
>> also be good to let people get some experience using variations of such
>> sugar before plopping sweetener like this onto such a central and
>> important library type. Though another thing I try and avoid is adding
>> implicit conversions to make things more "readable" like this, because
>> in so doing, I also make it less standard (which makes it harder to read
>> in that way).
>
> Good points, all of them. I'm not sure what the best strategy is for
> people getting some experience with it, other than annotating it
> 'experimental'.
>
> Another idea I'm going to play with is whether Option[T] could inherit
> from Seq[T] (or whatever it is in scala 2.8 now). Methods like 'map',
> 'foreach', 'filter', 'size', etc. I think will be compatible, and maybe
> even sensible. Whether others are remains to be seen ...
>
>

Sam Stainsby
Joined: 2009-01-14,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

On Tue, 29 Sep 2009 20:27:04 -0700, Bill Venners wrote:

> By experience I meant implementing it with an implicit in your own code
> and using it for a while. See how it goes that way. With experience you
> may decide you clearly like ifSome over ifDefined, or decide that it
> wasn't such a good idea after all and you'd rather just use a pattern
> match, etc.

I can confirm that this works:

sealed class OptionIfSomeExtension[A](option:Option[A]) {
def ifSome[B](f:A=>B):Option[B] = option.map[B](f)
def otherwise[B>:A](default: =>B):B = option.getOrElse(default)
}

object OptionIfSomeImplicits {
implicit def toOptionIfSomeExtension[A](option:Option[A])
= new OptionIfSomeExtension(option)
}

and so use:

import OptionIfSomeImplicits._

where needed.

The part I'm struggling with is adding an 'ifNone' method, as per
Viktor's suggestion, that can be followed sensibly with the same
'otherwise' method :-/

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: a little sugar for Option

It's all in Scalaz, albeit generalised.

Sam Stainsby wrote:
> On Tue, 29 Sep 2009 20:27:04 -0700, Bill Venners wrote:
>
>
>> By experience I meant implementing it with an implicit in your own code
>> and using it for a while. See how it goes that way. With experience you
>> may decide you clearly like ifSome over ifDefined, or decide that it
>> wasn't such a good idea after all and you'd rather just use a pattern
>> match, etc.
>>
>
> I can confirm that this works:
>
> sealed class OptionIfSomeExtension[A](option:Option[A]) {
> def ifSome[B](f:A=>B):Option[B] = option.map[B](f)
> def otherwise[B>:A](default: =>B):B = option.getOrElse(default)
> }
>
> object OptionIfSomeImplicits {
> implicit def toOptionIfSomeExtension[A](option:Option[A])
> = new OptionIfSomeExtension(option)
> }
>
> and so use:
>
> import OptionIfSomeImplicits._
>
> where needed.
>
> The part I'm struggling with is adding an 'ifNone' method, as per
> Viktor's suggestion, that can be followed sensibly with the same
> 'otherwise' method :-/
>
>
>
>

Florian Hars
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

Tony Morris schrieb:
> def f(v: Option[Int]) {
> printf(if(v.isDefined) "=" + v.get else "=?")
> }

Far too verbose.

def f(v: Option[Any]) {
printf((v :\ "=?")((x,y) => "=" + x))
}

- Florian

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: a little sugar for Option

Florian Hars wrote:
> Tony Morris schrieb:
>
>> def f(v: Option[Int]) {
>> printf(if(v.isDefined) "=" + v.get else "=?")
>> }
>>
>
> Far too verbose.
>
> def f(v: Option[Any]) {
> printf((v :\ "=?")((x,y) => "=" + x))
> }
>
> - Florian
>
>
>
I'm not sure if you are joking. The beauty of this is that I can pretend
you are.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland