This is not your father's AnyVal

245 views
Skip to first unread message

Paul Phillips

unread,
Sep 11, 2012, 9:00:01 PM9/11/12
to scala-l...@googlegroups.com
AnyVal as a type was approximately useless before now; it has become even worse than useless (again, as a type.  As the only means of telling the compiler "make me a value class", it has solid job security.)

So as I bring up every year or so, the inheritance hierarchy is broken.  There is nothing useful which can be done with AnyVal.  I defy anyone to demonstrate a use for AnyVal which justifies AnyVal on its own merits.  It is only a source of bugs (quite a lot of them, actually) to no advantage.

There are easy answers here. "Never infer AnyVal" is the easiest, first, and best.  Others are: remove AnyVal from the hierarchy completely, so it isn't meaningful to extend AnyVal other than to become a value class.  If feeling frisky, structure the nine original AnyVals in some way that actually lets you get at their shared properties, like the fact that Byte/Short/Char/Int/Long are almost identical modulo size, whereas Boolean and Unit have about as much to do with them (or with one another) as they do with ConcurrentHashMap.  Or do nothing with them; it's not like we'd be losing anything if we removed AnyVal and replaced it with nothing.  It's all easy to do.  All we need is agreement.

If someone thinks AnyVal has some reason for existing, please make the case so I don't have to be in the dark about all the powerful abstractions being formed around AnyVal outside my field of vision.

// It's a list of Longs...
scala> List(1, 1L)
res1: List[Long] = List(1, 1)

// It's a list of list of AnyVals! What will you do with it which you couldn't do with a List of Anys?
scala> List(List(1), List(1L))
res2: List[List[AnyVal]] = List(List(1), List(1))

// Of course it is!
scala> def f(x: AnyVal) = x ; f("abc")
f: (x: AnyVal)AnyVal
res3: AnyVal = abc

// Oops, capt. special case strikes again
scala> Array(1, 1L, 1f, true).head.getClass
java.lang.ClassCastException: java.lang.Integer cannot be cast to scala.AnyVal

// Let's try to justify this next sequence from first principles:
scala> def f(x: AnyVal) = x
f: (x: AnyVal)AnyVal

scala> f(Nil)
<console>:9: error: type mismatch;
 found   : scala.collection.immutable.Nil.type
 required: AnyVal
Note that implicit conversions are not applicable because they are ambiguous:
 both method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
 and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
 are possible conversion functions from scala.collection.immutable.Nil.type to AnyVal
              f(Nil)
                ^

scala> implicit class Bippy(val xs: List[Int]) extends AnyVal { def valueClassMethod = "bippy" }
defined class Bippy

scala> f(Nil)
res1: AnyVal = Bippy@1c395774


You didn't write Bippy so that lists could be magically transformed into a new, utterly unrelated type.  You did it to add "valueClassMethod".  What could this property ever buy anyone beyond bugs.

Erik Osheim

unread,
Sep 11, 2012, 9:09:41 PM9/11/12
to scala-l...@googlegroups.com
On Tue, Sep 11, 2012 at 06:00:01PM -0700, Paul Phillips wrote:
> There are easy answers here. "Never infer AnyVal" is the easiest, first,
> and best. Others are: remove AnyVal from the hierarchy completely, so it
> isn't meaningful to extend AnyVal other than to become a value class. If
> feeling frisky, structure the nine original AnyVals in some way that
> actually lets you get at their shared properties, like the fact that
> Byte/Short/Char/Int/Long are almost identical modulo size, whereas Boolean
> and Unit have about as much to do with them (or with one another) as they
> do with ConcurrentHashMap. Or do nothing with them; it's not like we'd be
> losing anything if we removed AnyVal and replaced it with nothing. It's
> all easy to do. All we need is agreement.

I would love to see AnyVal gone, even just to avoid useless inferences.

Structuring the nine other classes sounds nice at face value, although
without tying into specialization (or something similar) I'm not sure
how useful it is to talk about any shared properties. So on reflection
I'd hold off. That said, if someone has a great idea for what could be
accomplished via a different hierarchy I'm definitely interested.

Like you said, now that we have value classes, any assumptions one
might have made about AnyVal's meaning are probably wrong now.

-- Erik
Reply all
Reply to author
Forward
0 new messages