Discussion:
[scala-language] Different behaviour from Option map in scala compared to Optional map in java
Marc Arndt
2016-04-17 10:27:09 UTC
Permalink
Hello,
while programming with java 8 and scala I discovered that both seem to have
a different behaviour with the method map in the classes Option in scala
and Optional in java.
In scala the method map in Option is implemented as followed:


* @inline final def map[B](f: A => B): Option[B] = if (isEmpty) None
else Some(f(this.get))*This method requires, that f doesn't return null.

In java the method map in Optional is implemented as followed:







* public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
{ Objects.requireNonNull(mapper); if
(!isPresent()) return empty(); else { return
Optional.ofNullable(mapper.apply(value)); } }*
This method does not require, that the given method returns a value not
null, it is also accepted to return null.

I'm not sure if this behaviour is intended.

Many Greetings
Marc
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
David Starner
2016-04-17 16:08:16 UTC
Permalink
Post by Marc Arndt
else Some(f(this.get))*This method requires, that f doesn't return null.
That just means that if f returns null, the map returns Some(null).
Post by Marc Arndt
I'm not sure if this behaviour is intended.
Scala treats null generally as being something that is supported for legacy
Java-compatibility reasons only. In that context, it makes perfect sense to
just pass through the null here. Java 8's choice may be reasonable in its
context, but less so for Scala.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Marc Arndt
2016-04-17 16:27:35 UTC
Permalink
Hi,
you're right it's not a bug, but I normally think that getting a Some
object means that it does not contain null, because null would be
represented with None.
This thinking leads to a NullPointerException when I try to use the
contained value in the returned Some object.
This is strange in my eyes because I would use the map method from Option
to prevent getting NullPointerExceptions.
Therefore I think it's more intuitive if map returns Option(f(this.get))
instead of Some(f(this.get)), because this would prevent a
NullPointerException if I use the returned Option object from map.

I'm asking, because I often use the map method from Option to wrap a
variable from an java object, which can be null, into an Option object,
which makes it possible to use map chains like: Option(a).map( _.getB
).map( _.isValid )
This is especially useful when I use java libraries like hibernate to
persist objects and their relations in a database and also want to use them
in scala.

Greetings
Marc
Post by David Starner
Post by Marc Arndt
else Some(f(this.get))*This method requires, that f doesn't return null.
That just means that if f returns null, the map returns Some(null).
Post by Marc Arndt
I'm not sure if this behaviour is intended.
Scala treats null generally as being something that is supported for
legacy Java-compatibility reasons only. In that context, it makes perfect
sense to just pass through the null here. Java 8's choice may be reasonable
in its context, but less so for Scala.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Naftoli Gugenheim
2016-04-17 16:42:15 UTC
Permalink
Post by Marc Arndt
Hi,
you're right it's not a bug, but I normally think that getting a Some
object means that it does not contain null, because null would be
represented with None.
That's not a valid assumption. There's nothing stopping you from writing
Some(null) anywhere. It course it's probably not a good idea, but it's no
better or worse than writing null on general.
It's true that *one* of the benefits of Option is to eliminate the need for
null, but at the end of the day it's just a tool, and it's up to you how to
use it.

This thinking leads to a NullPointerException when I try to use the
Post by Marc Arndt
contained value in the returned Some object.
This is strange in my eyes because I would use the map method from Option
to prevent getting NullPointerExceptions.
Therefore I think it's more intuitive if map returns Option(f(this.get))
instead of Some(f(this.get)), because this would prevent a
NullPointerException if I use the returned Option object from map.
I'm asking, because I often use the map method from Option to wrap a
variable from an java object, which can be null, into an Option object,
which makes it possible to use map chains like: Option(a).map( _.getB
).map( _.isValid )
This is especially useful when I use java libraries like hibernate to
persist objects and their relations in a database and also want to use them
in scala.
Greetings
Marc
Post by David Starner
Post by Marc Arndt
else Some(f(this.get))*This method requires, that f doesn't return null.
That just means that if f returns null, the map returns Some(null).
Post by Marc Arndt
I'm not sure if this behaviour is intended.
Scala treats null generally as being something that is supported for
legacy Java-compatibility reasons only. In that context, it makes perfect
sense to just pass through the null here. Java 8's choice may be reasonable
in its context, but less so for Scala.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Jérôme M. Berger
2016-04-17 17:27:40 UTC
Permalink
Post by Marc Arndt
I'm asking, because I often use the map method from Option to wrap a
variable from an java object, which can be null, into an Option object,
which makes it possible to use map chains like: Option(a).map( _.getB
).map( _.isValid )
This is especially useful when I use java libraries like hibernate to
persist objects and their relations in a database and also want to use them
in scala.
In that case, you want to use flatMap instead of map. This allows you
to be explicit about the possibly null value:
Option(a).flatMap(Option(_.getB)).map(_.isValid)

Jerome
--
mailto:***@free.fr
http://jeberger.free.fr
Jabber: ***@jabber.fr
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Simon Ochsenreither
2016-04-17 21:20:12 UTC
Permalink
Post by Marc Arndt
you're right it's not a bug, but I normally think that getting a Some
object means that it does not contain null, because null would be
represented with None.
This thinking leads to a NullPointerException when I try to use the
contained value in the returned Some object.
This is strange in my eyes because I would use the map method from Option
to prevent getting NullPointerExceptions.
Therefore I think it's more intuitive if map returns Option(f(this.get))
instead of Some(f(this.get)), because this would prevent a
NullPointerException if I use the returned Option object from map.
Option[T] doesn't (and can't) add additional constraints on T. If null is a
valid value of T, Some(null) is a perfectly fine value of Option.
Adding ad-hoc null-handling to some types would be more or less just trying
to paper over the issue that most things in Scala/on the JVM are nullable.
The problem should be fixed (maybe in Dotty), not the symptoms.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Kevin Wright
2016-04-17 21:41:18 UTC
Permalink
A trivial example can serve to demonstrate the problem of adding magical
behaviour around nulls.

val theMap = Map(1 -> “one”, 2 -> null)
println(theMap get 1)
println(theMap get 2)
println(theMap get 3)

Three different results
 “one”, Some(null), None
There’s a difference in meaning here that Scala will preserve unless you
explicitly request otherwise

Some(null) indicates that there *is* a value present, and that value is null
(which is a valid subtype of String)
None indicates that the value was absent from the map

This sort of thing almost never occurs in idiomatic Scala code, it results
from Java intro, but it’s not entirely unknown.

If you want to drop that distinction, then calling Option(x) will return
Some(x), or None if x is null
This can also be used if you already have an Option that maybe contains null,
by calling:
theDubiousOption flatMap {Option(_)}


On 17 April 2016 at 22:20, Simon Ochsenreither <
Post by Marc Arndt
you're right it's not a bug, but I normally think that getting a Some
Post by Marc Arndt
object means that it does not contain null, because null would be
represented with None.
This thinking leads to a NullPointerException when I try to use the
contained value in the returned Some object.
This is strange in my eyes because I would use the map method from Option
to prevent getting NullPointerExceptions.
Therefore I think it's more intuitive if map returns Option(f(this.get))
instead of Some(f(this.get)), because this would prevent a
NullPointerException if I use the returned Option object from map.
Option[T] doesn't (and can't) add additional constraints on T. If null is
a valid value of T, Some(null) is a perfectly fine value of Option.
Adding ad-hoc null-handling to some types would be more or less just
trying to paper over the issue that most things in Scala/on the JVM are
nullable. The problem should be fixed (maybe in Dotty), not the symptoms.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Vlad Patryshev
2016-04-17 16:30:38 UTC
Permalink
I agree; Some(null) is an abomination, and Option(f(this.get)) would make
more sense.

Actually, in my class Result I wrap all these things (exceptions and nulls)
even for filter and collect, not just map. Meaning, if the predicate called
in filter() throws an exception, that's a legit error, and should be
wrapped as Bad(exception). I think, David Pollak's Box does the same.

Thanks,
-Vlad
Post by Marc Arndt
Hello,
while programming with java 8 and scala I discovered that both seem to
have a different behaviour with the method map in the classes Option in
scala and Optional in java.
else Some(f(this.get))*This method requires, that f doesn't return null.
* public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
{ Objects.requireNonNull(mapper); if
(!isPresent()) return empty(); else { return
Optional.ofNullable(mapper.apply(value)); } }*
This method does not require, that the given method returns a value not
null, it is also accepted to return null.
I'm not sure if this behaviour is intended.
Many Greetings
Marc
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Sébastien Doeraene
2016-04-17 16:36:14 UTC
Permalink
Hello,

There are good reasons that .map() does not change `null` to `None`. If it
did that, I would never be able to use a `.map` on an `Option[T]` where I
myself do not know what T will be (typically, because I'm writing a
library). The user of my library might very well use my library with a T
that can reasonably contain null values. In the insides of my library,
using a null-handling .map() would *destroy* the data of my user. In other
words, such a map would not be completely *type parametric*.

If you want a .map() that takes care of `null` returned by its function,
you can use `.flatMap(x => Option(f(x)))`.

Cheers,
Sébastien
Post by Vlad Patryshev
I agree; Some(null) is an abomination, and Option(f(this.get)) would make
more sense.
Actually, in my class Result I wrap all these things (exceptions and
nulls) even for filter and collect, not just map. Meaning, if the predicate
called in filter() throws an exception, that's a legit error, and should be
wrapped as Bad(exception). I think, David Pollak's Box does the same.
Thanks,
-Vlad
Post by Marc Arndt
Hello,
while programming with java 8 and scala I discovered that both seem to
have a different behaviour with the method map in the classes Option in
scala and Optional in java.
else Some(f(this.get))*This method requires, that f doesn't return null.
* public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
{ Objects.requireNonNull(mapper); if
(!isPresent()) return empty(); else { return
Optional.ofNullable(mapper.apply(value)); } }*
This method does not require, that the given method returns a value not
null, it is also accepted to return null.
I'm not sure if this behaviour is intended.
Many Greetings
Marc
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Naftoli Gugenheim
2016-04-17 16:44:32 UTC
Permalink
Post by Vlad Patryshev
I agree; Some(null) is an abomination,
Then don't return null in the function you pass map! But if you do return
null that's your choice, it makes zero sense for map to steamroll over your
choice.

and Option(f(this.get)) would make more sense.
Post by Vlad Patryshev
Actually, in my class Result I wrap all these things (exceptions and
nulls) even for filter and collect, not just map. Meaning, if the predicate
called in filter() throws an exception, that's a legit error, and should be
wrapped as Bad(exception). I think, David Pollak's Box does the same.
Thanks,
-Vlad
Post by Marc Arndt
Hello,
while programming with java 8 and scala I discovered that both seem to
have a different behaviour with the method map in the classes Option in
scala and Optional in java.
else Some(f(this.get))*This method requires, that f doesn't return null.
* public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
{ Objects.requireNonNull(mapper); if
(!isPresent()) return empty(); else { return
Optional.ofNullable(mapper.apply(value)); } }*
This method does not require, that the given method returns a value not
null, it is also accepted to return null.
I'm not sure if this behaviour is intended.
Many Greetings
Marc
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...