scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Allow Implicit Modifier on Parameters to Anonymous Methods #1492

Closed scabug closed 13 years ago

scabug commented 15 years ago

Specifically, I would like to be able to do the following:

val result = higherOrderMeth { implicit a: Int =>
  // do implicit-y things with a
}

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).

scabug commented 15 years ago

Imported From: https://issues.scala-lang.org/browse/SI-1492?orig=1 Reporter: @djspiewak

scabug commented 15 years ago

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
}
scabug commented 14 years ago

@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.

scabug commented 14 years ago

@odersky said: (In r19688) Allow implicit modifier on single-parameter function literals. Fixes and closes #1492.

scabug commented 14 years ago

@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"

scabug commented 14 years ago

@odersky said: Will be fixed in next checkin, thanks.

scabug commented 14 years ago

@jorgeortiz85 said: This is awesome! Thanks Martin!

If it's not asking too much, can we also have:

for (implicit a <- ...) {
  ...
}
scabug commented 14 years ago

@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.

scabug commented 14 years ago

@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.

scabug commented 14 years ago

@odersky said: (In r20229) Closed #1492. review by extempore

SethTisue commented 4 years ago

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 commented 4 years ago

SethTisue unassigned odersky 1 minute ago

oops, misclick

djspiewak commented 4 years ago

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!

som-snytt commented 4 years ago

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 }