I’m also not super convinced, but if we’re going to do it, I want the best version of it that we can think of, and I think the aggregate literal = relative scoping unification is a step in that direction.
I haven’t been able to think of intentional restrictions that increase the safety and clarity. And yes, I use C++ also, and yes, I also find that the clarity suffers in many instances. Part of that is C++'s propensity for adding a new feature if there is any use case covered by it, and thus tending to accumulate multiple alternatives for doing the same thing, but mostly it’s just that {2, 5, true}
is pretty opaque, whether you spell it with braces, brackets, or double-dot parens.
One could try unlocking it only in a varargs context, so
val p: Person = ..("Leslie", ..(1994, 7, 8))
wouldn’t work, but
val ps: Seq[Person] = ..(
..("Leslie", ..(1994, 7, 8)),
..("Alex", ..(1993, 7, 8)),
)
would. But this doesn’t make Person("Chris", Birthday(1949, 12, 31))
any less annoying to type.
And since you couldn’t stop the apply
version for relative scoping if everything was fair game, you would have to do something like restrict to stable identifiers (val
and object
) to get
shape.draw(Line(2.5), ..Red)
to work (and the Line
part wouldn’t work because it’s not varargs).
You could have to opt in with a keyword, but that would be practically useless because you can’t expect the entire ecosystem to change, and there are lots of places where you otherwise would have a lot of redundancy.
So I think the problem is that the feature requires the kind of care that is honestly pretty difficult to apply at the time, because of course you know the types, this is super obvious…while you’re writing it. The new hire, two years later, does not find it obvious. Neither do you, when you come back to it after two years and they’re all, “What even is this?!”
So that leaves gating it behind a language.relativeScoping
import, and hoping that this induces people to only reach for the feature in the cases where it’s most justified. And we maybe could provide a rewrite tool where the compiler would fill in the ..
(or .
or whatever we decide, if we do this) as a backstop against uninterpretability.
That’s all possible and has some precedent, which leaves me on the fence as to whether this is a good idea or not.