Closed scabug closed 13 years ago
Imported From: https://issues.scala-lang.org/browse/SI-1492?orig=1 Reporter: @djspiewak
Nathan Bronson (nbronson) said: It would also be useful to have this capability in for comprehensions, which for an STM might give something like:
for (implicit txn <- atomic) {
// body
}
@jesnor said: Are you suggesting that:
(implicit i : Int) => {...}
// Or with type inference: implicit i => {...}
should be equivalent to:
(i : Int) => { implicit val _ = i; ... }
// Or with type inference: i => { implicit val _ = i; ... }
If so, I think it's a valuable addition to the language.
@odersky said: (In r19688) Allow implicit modifier on single-parameter function literals. Fixes and closes #1492.
@ijuma said: Thanks, Martin. I spotted a spelling mistake in the spec diff (last word):
"A named parameter of an anonymous function may be optionally precdeded"
@odersky said: Will be fixed in next checkin, thanks.
@jorgeortiz85 said: This is awesome! Thanks Martin!
If it's not asking too much, can we also have:
for (implicit a <- ...) {
...
}
@paulp said: This is really cool, but I'm going to be an ingrate and reopen it because it's really hard to use. I had to analyze the diff to the parser to even figure out what syntax it might possibly accept -- none of my many guesses ever parsed.
Example: I have a method mainMethod which I use thusly.
def mainMethod(f: MethodVisitor => Unit): Unit = { ... }
// from elsewhere
cw mainMethod { mw =>
implicit val _mw = mw
// the methods being called here by way of implicit take an implicit mw
("java/lang/System" getStatic "out")
("java/io/PrintStream" invokeVirtual "println")("Hello world!")
("java/lang/System" invokeStatic "setProperty")("propfoo", "valuebar")
}
So naturally I'd be pleased to be able to write:
cw mainMethod { implicit mw => ...
But that does not parse. The only way I can get it to parse are when I explicitly type it prior to the parameter being used. I failed to find any way to annotate the type of the parameter or to use an anonymous parameter. So here is how it looks if I accept the limitations:
val body: MethodVisitor => Unit = implicit mw => {
("java/lang/System" getStatic "out")
("java/io/PrintStream" invokeVirtual "println")("Hello world!")
("java/lang/System" invokeStatic "setProperty")("propfoo", "valuebar")
}
cw mainMethod body
But this is far inferior to the original version.
@odersky said: The problem here was that you could not write an anonymous function with implicit parameter in braces. This will be fixed shortly. Test in implicits.scala.
@odersky said: (In r20229) Closed #1492. review by extempore
Allow implicit modifier on single-parameter function literals
curious, why only single-parameter?
this came up today on Gitter
SLS 6.23 says "A named parameter of an anonymous function may be optionally preceded by an implicit modifier.", so the single-parameter restriction isn't in the spec language
SethTisue unassigned odersky 1 minute ago
oops, misclick
curious, why only single-parameter?
There are other rather odd restrictions associated with this, as well, such as the fact that the implicit
parameter cannot have an explicit type!
I suspect this is all because it's a relatively obscure feature which was originally added somewhat rapidly in response to my ill-considered suggestion (which itself came about because I was trying to thread STM transaction identity in a syntactically-nice way). Realistically, I think this bit of syntax could use some attention in Scala 3 (probably 3.1 at this point), removing some of these gotchas and integrating it more cleanly into the language. This could all be done in a fully compatible way, since the syntax would be a strict superset (implicit
is already forbidden as an identifier).
If I were truly motivated, I would draft a SIP. But this hasn't really crossed my threshold of motivation in the thirteen-ish years since this was added, which perhaps is the real answer to the question of "why": no one has felt strongly enough to do anything about it!
In Scala 3, the implicit
is how you enable parenless arg syntax. (f
is still ok as of 0.26, but please don't tell them!) (Edit: maybe it's a generous easter egg?)
def f(xs: List[Int]) = xs.map { implicit x: Int => implicitly[Int] + 1 }
def g(xs: List[Int]) = xs.map { x: Int => x + 1 }
Specifically, I would like to be able to do the following:
As of 2.7.1, this triggers a parse error. As far as I can tell, allowing this should not affect soundness and will not introduce any ambiguities in the grammar.
This capability is useful for situations like my implicit STM which uses function values which take implicit parameters. Without this functionality, every function used in such a fashion must be declared as a full, named function. This is ugly and too heavily drains the imagination (seeking unique identifiers).