score:3

You are correct; the new is not mandatory. They could have defined the instance method List#:: like this just as well:

def ::[U >: T](x: U): List[U] = scala.::(x, this)

(Note that we have:

type :: = collection.immutable.::
val  :: = collection.immutable.::

defined in the scala package object; the first is why your new scala.::(x, this) works, and the second is why my scala.::(x, this) works.)

The form the library uses calls the constructor directly, as yours does. The alternative calls the apply method of the synthetic companion object generated for the :: case class, which simply calls the constructor anyway. Perhaps calling the constructor was deemed clearer, or more efficient? (Efficiency gains should be close to nothing, though, since if the compiler doesn't inline the call to apply, the JVM will.) I suppose the most compact form:

def ::[U >: T](x: U) = ::(x, this)

could be mistaken for some wacky (i.e., impossible) sort of recursive invocation, and at any rate blurs the distinction between the class called :: and the List method called ::, which Prof. Odersky takes pains to keep separate in order to maximize reader comprehension.

Hope this helps.

score:7

With case classes you automatically get a companion object whose apply method calls the constructor, in the same way as you can do this with an ordinary class:

class Foo(val value: Int) 
object Foo { def apply(value: Int) = new Foo(value) }

val x = new Foo(42)  //
val y = Foo(42)      // both work the same

You can instantiate case classes with new if you want to. It might in theory be slightly faster because it doesn't have to go via the companion object's apply method, but I tried a quick benchmark and saw absolutely no difference in performance, so I guess it's optimised by the compiler, or just an immeasurably small difference compared to the actual construction.

So I don't think the new in the example you give has any significance and could just as well have been left out.


Related Query

More Query from same tag