I’d be interested in discussing a SIP (as I missed the discussion the first time round).
I’d like to add the following points:
I’ve been by people working on Scalac and Dotty that the compile-time cost of supporting relative imports is disproportionate to their value. The reason, as briefly explained to me, modulo my recollection, is that in a language with only absolute imports, the process of naming is a quite trivial lookup in a limited number of imported scopes, all of which are fully-qualified, whereas permitting relative imports requires some amount of typechecking to be completed in order to resolve names, and naming and typechecking become much more interleaved.
I agree, therefore, with @olafurpg’s suggestion that absolute imports should be “the default” and relative imports should come with a “syntax cost”. The claim that there’s a compile-time cost for relative imports is very much consistent with the comprehension cost for the programmer.
I think that the syntax
_root_ is very ugly, and should be removed from the language. There’s no other precedent anywhere in Scala for giving something a name surrounded by underscores, and it is an anomaly. It would be great to replace it with something more consistent with the ergonomics of Scala. Historically, IIRC, it was chosen so as to not require the introduction of a new special keyword (
root) and to not be likely to clash with existing keywords in use. Dotty doesn’t have so many qualms about introducing new keywords, so I don’t think this applies any more.
My preference would be to deprecate
_root_, and to make absolute imports default, and
import _.foo seems like perfectly reasonable syntax for relative imports.
If we took this approach, there’s no reason why we couldn’t have a long transition period where both syntaxes are supported, before rewriting the compiler to take advantage of these promised compile-time speedups…
I broadly support the idea of being able to nest imports, not so much because I think it’s going to be really useful, but because the Principle of Least Surprise says they should be composable.
Tangentially, I heard a suggestion somewhere, some time ago, that Scala would be more understandable if imports did not introduce implicits into scope, unless prefixed with the
implicit keyword. For example, you would require
implicit import scala.concurrent.ExecutionContext.Implicits.global if you wanted to have it available in scope to use implicitly. I have no strong feelings about this. (I think it would be a radical change with both advantages and disadvantages, which would more or less balance out…) But I raise it here in case other people want to discuss it.
That’s all I’ve got.