I would hope that it would only be used in a local scope. Certainly, such implicits should not be imported. So I donât think itâs a dealbreaker.
At least in IntelliJ, from the list I can preview the implementation or jump to it. So again, if used sparingly I think itâs okay.
I think we have to separate implicit val
s and implicit def
s. For def
s thatâs certainly valid. However my response would also depend on what you mean by overloaded.
If you mean as far as peopleâs intuition and increasing the learning curve, I think itâs consistent enough with other places _
is used that the meaning should be obvious. (It would help if we stop telling people _
is highly overloaded. While true in terms of the spec, and important to understand in more non-obvious places like type parameters, I think a better way to teach it is that _
is a wildcard and Scala accepts wildcards in a lot of contexts, whenever it makes sense.)
If you mean in the sense of increasing the footprint of the language grammar or increasing the complexity of the compiler codebase, so for implicit def
I agree. For implicit val
, maybe itâs naive of me to say this, but it would seem this could be implemented by lifting some restrictions and simplifying the grammar and code. The way I see it, weâre basically saying (1) _
is a pattern not an identifier [should be a simple grammar change that doesnât affect its size], and (2) an implicit val with a pattern not an identifier, while not assigning to the expression a user-addressable name, it nevertheless exists within the local scope [perhaps because the compiler will assign it a generated name with a private[this]
or local-only scope]. Again, while an assumption from ignorance, it seems like itâs just a slight tweak of the rules in a way that makes things more regular.
These two suggestions are entirely orthogonal, though. Well, except that #2 is more intuitive the way things are now, that _
is actually an identifier in the sense that you canât do two val _
s.
Wait, I just did some testing. The current behavior is a bit contradictory.
A. implicit val _ : Int = 10; implicitly[Int]
works. This seems to imply that either _
is an identifier, or that #2 is implemented already.
B. implicit def _ : Int = 10
does not compile: identifier expected but '_' found.
Why should it work for def but not val? The answer would seem to be that val supports patterns while def does not. So _
is interpreted as a pattern!
C. val _ = 1; val _ = 2
does not compile: _ is already defined as value _
So _
is interpreted as an identifier! (For example, using a tuple2 pattern and annotating 1
and 2
as Any
does compile.)
So while the two proposals are orthogonal, #2 is necessary if we want to implement #1 while preserving the behavior of (A). And if we donât implement #1 â if we say that _
can be an identifier â then in order to remove the above contradiction, we either implement #2 and allow (B) or disallow (A).
In short, the consistent options are:
- (A) and (C) compile and work â implement #1 and #2. (B) doesnât compile because
def
s canât use patterns.
- (A) and (B) compile and work â we donât implement #1 or #2, instead we say
_
is a valid identifier
- Only (C) compiles and works â we implement #1 so thereâs no redefinition, but without #2 (A) wonât work since
10
is not stored in the scope.
If we would implement #2, itâs not clear what to do for other pattern types. For example a constructor pattern that uses an extractor that returns some âunrelatedâ value.
All of this doesnât help for the implicit def
case. Iâm not sure how important that is. If something needs to be a def, it probably is being reused enough that leaving off the name has no justification. (Usually scala allows shorter forms of things in order to support prototyping, scripting, etc., or syntactic sugar for patterns it encourages.) Besides the generalization â allowing def
s to be patterns â has some problems. def (filter, filterNot) ... = partition ...
doesnât seem very efficient ;).