At least in my opinion. Can we get rid of "new" at least in the syntax?
Requiring "new" for value classes feels a lot like the early design mistakes in Java, e.g. like new java.lang.Integer(1) and doesn't work well with the current style of things like BigInt(1) or BigDecimal("1.0"). The existing AnyVal classes don't support something like new Int(1), too.
In fact, the whole SIP emphasizes that the wrapping has no identity nor semantic meaning and the instance is only created as a last resort.
Using "new" for it is pretty much contradicting that. "new" is all about creating a distinct, freshly allocated instance with its own identity and guarantees that there is _really_ a new, separate instance created.
I think we should be really consistent here and drop the "new", so that
ValueClass("Foo")
desugars to a either
a) a constructor invocation (if there is no apply in the companion object)
b) a call to apply in the companion object which invokes a private constructor (if there is an apply).
(I know there is "case" and the possibility to write an additional apply method, but I think developers should be correct-by-default and not correct-with-additional-effort.)
What do you think?
Thanks,
Simon
It's technically impossible as things stand. We have to generate the apply very early, so that every use site can see it. But we see the fact that we have a value class only later, when we analyze its parents and see that AnyVal is among them.
I pretty much think value classes imply case by default:
case classes synthesize a lot of those methods which are synthesized for value classes, too. It is just that the implementation is different. Just add an apply to it and be consistent.
As I have already written, we can't. A case class is known as such to the parser by the presence of the keyword `case`. A value class is only knownby the fact that it's parent is AnyVal, which requires name resolution and type analysis to determine.
Personally, I think case classes present already enough entanglement of features. No need to extend that to other types of classes; in particular ones that exist primarily for performance. Remember, one of the primary use cases of a value class is as implicit wrappers. I need none of the case class methods for such a wrapper, so why insist on generating them?
Hi Martin,As I have already written, we can't. A case class is known as such to the parser by the presence of the keyword `case`. A value class is only knownby the fact that it's parent is AnyVal, which requires name resolution and type analysis to determine.
Ah right, yes. Forgot that.
Personally, I think case classes present already enough entanglement of features. No need to extend that to other types of classes; in particular ones that exist primarily for performance. Remember, one of the primary use cases of a value class is as implicit wrappers. I need none of the case class methods for such a wrapper, so why insist on generating them?
Sorry, I wasn't clear enough. My comparison between case and AnyVal was intended to show that they both have special rules to what happens behind the scenes to stuff like toString, equals, etc. and focused on some possible implementation detail.
In the end, I just think new needs to be gone, independently of the approach to achieve that.
I'm very sympathetic to “It's hard to implement in the compiler”, but this should never have an impact when deciding what's the correct thing to do for the user.