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

SAM types don't work for zero parameter methods #10555

Closed
fommil opened this issue Oct 18, 2017 · 8 comments
Closed

SAM types don't work for zero parameter methods #10555

fommil opened this issue Oct 18, 2017 · 8 comments
Labels

Comments

@fommil
Copy link

fommil commented Oct 18, 2017

SAM types don't work for methods that don't take params
e.g. this type class

 trait Default[A] {
  def default: A
}

can't have instances defined, e.g.

implicit val string: Default[String] = ""

or

implicit val string: Default[String] = { () => "" }

have to do it the old fashioned way

@SethTisue
Copy link
Member

SethTisue commented Oct 26, 2017

It's very much intentional that implicit val string: Default[String] = "" does not compile. No function literal, no SAM conversion (reference: SLS 6.26.1). (No, Sam: no SAM.)

As for the other variant, it works if default takes a single empty parameter list:

scala> trait Default[A] { def default(): A }
defined trait Default

scala> (() => ""): Default[String]
res0: Default[String] = $$Lambda$1080/665564874@696db620

This is also as specified: "the method m must have a single argument list" (SLS 6.26.1 again).

Whether it was intentional that the no-parameter-lists-at-all case is disallowed by the spec (and by the implementation), I don't know. Offhand, I think it might simply be an oversight. @adriaanm?

@SethTisue SethTisue added the sam label Oct 26, 2017
@SethTisue
Copy link
Member

fwiw, dotc agrees with scalac here

@joroKr21
Copy link
Member

joroKr21 commented Dec 18, 2017

To me this just adds to the confusion with empty parameter lists:

  • At call site any number of them are conflated
  • Eta expansion works, but doesn't conflate and is deprecated
  • Eta expansion works with no parameter lists and is not deprecated
  • SAM types do not work without an empty parameter list

Seems like whatever you choose you end up with a deprecation or a lint warning.

Edit (workaround):

trait Default[A] {
  protected def leDefault(): A
  def default: A = leDefault()
}

@adriaanm
Copy link
Contributor

adriaanm commented Apr 26, 2018

At call site any number of them are conflated

We'll deprecate this in 2.14. Scala 3 will require explicit () for methods that define an empty argument list (except for Java-defined methods)

Eta expansion works, but doesn't conflate and is deprecated
Eta expansion works with no parameter lists and is not deprecated

Not sure I fully understood the difference between these two cases, but 2.13 will not eta-expand 0-ary methods: scala/scala#6475

SAM types do not work without an empty parameter list

Given that SAM is a notion we got from Java, where you cannot define a method without an argument list, I don't think we should allow this.

@adriaanm
Copy link
Contributor

(Also note that the main purpose of having no-argument-list methods is to hide the distinction between a val and a def. Since that distinction would leak if we got SAM in the mix, that's another reason to exclude this case.)

@fommil fommil closed this as completed Apr 26, 2018
@joroKr21
Copy link
Member

Eta expansion works, but doesn't conflate and is deprecated
Eta expansion works with no parameter lists and is not deprecated

Not sure I fully understood the difference between these two cases, but 2.13 will not eta-expand 0-ary methods: scala/scala#6475

I guess I meant this:

scala> def foo()()() = 42
foo: ()()()Int

scala> foo _
res0: () => () => () => Int = $$Lambda$1053/1955226954@1d8b0500

scala> def bar = 42
bar: Int

scala> bar _
res1: () => Int = $$Lambda$1054/1361755941@515ab3f2

But I totally agree that the recent developments you mentioned are an improvement.

@adriaanm
Copy link
Contributor

Glad to hear it, and very grateful for being pushed in the right direction here :-) Keep up the good work!

@dwijnand
Copy link
Member

Given that SAM is a notion we got from Java, where you cannot define a method without an argument list, I don't think we should allow this.

Seems like a weak point to me. We get lots of things from Java and extend them. Why "got from Java" should draw the line here.

Also note that the main purpose of having no-argument-list methods is to hide the distinction between a val and a def. Since that distinction would leak if we got SAM in the mix, that's another reason to exclude this case.

Why/how would that leak?

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

No branches or pull requests

5 participants