Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Implicit Modifier on Parameters to Anonymous Methods #1492

Closed
scabug opened this issue Nov 9, 2008 · 14 comments
Closed

Allow Implicit Modifier on Parameters to Anonymous Methods #1492

scabug opened this issue Nov 9, 2008 · 14 comments

Comments

@scabug
Copy link

scabug commented Nov 9, 2008

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
Copy link
Author

scabug commented Nov 9, 2008

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

@scabug
Copy link
Author

scabug commented Aug 13, 2009

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
Copy link
Author

scabug commented Nov 2, 2009

@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
Copy link
Author

scabug commented Nov 17, 2009

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

@scabug
Copy link
Author

scabug commented Nov 17, 2009

@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
Copy link
Author

scabug commented Nov 17, 2009

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

@scabug
Copy link
Author

scabug commented Nov 17, 2009

@jorgeortiz85 said:
This is awesome! Thanks Martin!

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

for (implicit a <- ...) {
  ...
}

@scabug
Copy link
Author

scabug commented Dec 17, 2009

@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
Copy link
Author

scabug commented Dec 18, 2009

@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
Copy link
Author

scabug commented Dec 18, 2009

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

@SethTisue
Copy link
Member

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
Copy link
Member

SethTisue unassigned odersky 1 minute ago

oops, misclick

@djspiewak
Copy link
Member

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
Copy link

som-snytt commented Sep 13, 2020

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 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants