Okay, so the feature isnât that named tuples have any relationship with case classes, but rather that the same literal notation that can be used for named tuples can also be used for case classes. That definitely makes the syntax change pull its weight better. (But I still think it leaves named tuples as not-shining-as-much-as-they-should.)
However, I note an asymmetry between the proposals as they stand.
val x = (speed = 14, destination = "Paris")
val y = [1, 3, 6, 10, 15]
In the first case there is no doubt that x
is a named tupleâyou just look at the code and see that thatâs what it is. (Possible exception: if we have an abstract class where val x: Trip
is defined, will val x
be a named tuple or a Trip
?.)
But in the proposal under consideration, val y
is determined by whatever set of givens happens to be in scope. In particular, we canât assume itâs a Seq[Int]
or IArray[Int]
or any other natural type; it could be a bitset for all we know.
I think itâs worth revisiting this part of the proposal (as I suggested before). As far as I know, no language allows distant import statements to determine the type of collection literals; itâs strictly an override when the type is known (which is why C# for instance allows partial type annotations). I think youâre right that:
However, the person may end up needing to care after all what the type isâfor instance, without H-M type inference, they may wish to factor out the collection creation, and then they need to know what type it is.
In the JSON example, in addition to the compiler yelling at them if they get it wrong, they can also just look at the schema, which clearly says IArray[String]
and List[Plugin]
. But in your original example, there was no good way to figure out the types.
I think that although you want to enable people to not care about the collection type, you also want to empower them to figure out the type without too much struggle.
If you merely had the equivalent of implicit conversions activated by default whenever [...]
was specified, then weâd be on the same kind of ground that we usually are with on-by-default implicit conversions and numeric widening and so on.
But if [...]
doesnât even have that, but rather acts like (...).into
where into
changes types based on givens and type inference, thatâs pretty weird. You can imagine an into
method that creates a named tuple from a larger named tuple (same types, but more names/types that are unused). But
val x = (first = "John", last = "Doe", age = 42).into
would just be weird. Who knows what is being picked out and why? Hiding the operation name by using [ ]
symbols instead of a name ( ).into
doesnât make the weirdness any less; it just alerts you less and thus is all the more perplexing when something non-obvious is going on.
âDonât use Scalaâwe added an innocent import statement to get our config right, and then our production system slowed down to 1/n speed because our Vectors silently got converted to Listâ sounds like just the sort of Reddit post that would happen about six months after someone actually started using the feature seriously.
(The post would be wrong, of course. âDonât use collection literalsâ is the appropriate reaction to that kind of unpleasant outcomeâbut that also is an argument against giving too much power to givens.)