10 Jul 2012 01:29
Re: The Option conundrum
Here's the peanut gallery: please do. There's been dozens of threads about Option that stumbled upon the fact that Some(null) is legal. I doubt I'd be affected in any way, since I use Option(x) to get Some(x), and that kills all top-level nulls. Lower level nulls might still exist (ie, Some(Some(null))), but I don't think I have anything like that. Now, it's easy for someone to say he doesn't care how much trouble that will give others, but I'll say it anyway. That's how Option should have worked from the start, and I suspect there's some code that will be simplified by it. Now, to the specific proposals: Maybe/Just is attractive, but I worry about the existing-documentation effect. I really would prefer this change to be as transparent as possible, and having to teach something new about a fundamental concept described in every single Scala book, and probably talked about by every scala blogger, daunts me. Nullabillity check is on my wish list for a long time, on the other hand. Not only it would be of use elsewhere, but, if you don't mind me saying so, there's a movement toward this alternative among fellow JVM languages. On Mon, Jul 9, 2012 at 7:24 PM, martin odersky <martin.odersky@...> wrote: > Now that we have value classes, the next optimization frontier is Option. I > have been looking at that lately. The idea is to unbox as follows: > > Option[T] ==> the boxed version of T (which is always a reference type) > Some(x) ==> the boxed version of x > None ==> null > > Here are some examples of unboxed representations: > > Option[String] ==> String > Option[Int] ==> Integer > Option[Option[Int]] ==> Option[Integer] > > Some(1) ==> new Integer(1) > Some("abc") ==> "abc" > Some(None) ==> None > Some(Some("abc")) => Some("abc") > > It all works out beautifully. Almost all instances of Some objects would be > eliminated. Scala maps could run at the same speed as Java maps because they > would return exactly the same runtime values, but without the danger of > NPEs. > > But there's one catch: Some(null) cannot be represented. According to the > translation scheme, Some(null) should translate to null, but that's already > reserved for None. So Some(null) needs to be the same as None. > > How big of a hassle would it be to outlaw Some(null)? At first sight this > expression looks pretty weird, anyway. Well, I tried by catching Some(null) > in an assert and rebuilding scala trunk and running the tests. I found 4 > violations: > > - Java map wrappers that map a null result to Some(null) if the key exists. > This one is is actually pretty dubious; Java treats null as missing, so why > should the wrapper do it otherwise? Besides, this "feature" alone slows down > get operations on Java maps that miss by a factor of 2! I would vote for > changing the behavior here. > > - Property wrappers that map a null property to Some(null). Not sure > whether this one is dubious or not. > > OK so far, but it gets worse > > - ScalaCheck implicit value generation,which represents the generated value > `null` by `Some(null)` > > - ForkJoin tasks in parallel collections which also represent a returned > value `null` by `Some(null)` > > It's likely that there will be more cases like the last two in Scala > codebases. These cases cannot be solved without major changes, i.e. going > off Option entirely and replacing it with a new type. Not an attractive > proposition to demand from your users. But it's tantalizing that the major, > sweeping optimizations of Option are out of reach just because of some > corner cases. > > What to do? > > We could invent a new special subtype of Option (Maybe, anyone?) that is > guaranteed to contain non null values only. Here are the core definitions: > > abstract class Option[+T] > abstract class Maybe[+T] extends Option[T] > class Some[T](x: T) extends Option[T] > class Just[T](x: T) extends Maybe[T] { require(x != null) } > object None extends Maybe[Nothing] > > This would let us migrate to Maybe everywhere we can guarantee that > Some(null) is not possible. But the added classes and concepts are a very > high price to pay. At least until in some distant future everybody will use > Maybe and Option is of historical interest only. But that day would be far > away. > > Another idea is (rather ironically) to take nullability more seriously. > Scala side-stepped the issue with the introduction of the Option type, so > even though I initially thought we need some notion of non-nullable type, > the fact that everybody used Option anyway made that quite redundant. But > now the very fact that references can be null prevents us to do a good job > compiling Option! If we embrace NonNull (which is already in the library but > not very well supported by the language yet), then we could optimize at > least > > Option[T with NonNull] to T > > And, with enough care, critical operations in the libraries such as Map#get > could return an Option of a non-null type, thereby avoiding Some-boxing. > That seems to be a price worth paying: You invest in more precise types and > get better performance in return. > > Cheers > > - Martin > > > > > > > > -- > Martin Odersky > Prof., EPFL and Chairman, Typesafe > PSED, 1015 Lausanne, Switzerland > Tel. EPFL: +41 21 693 6863 > Tel. Typesafe: +41 21 691 4967 > -- -- Daniel C. Sobral I travel to the future all the time.
RSS Feed