Skip to content

2.13: confusing error when using infix for nullary method #11461

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

Closed
lrytz opened this issue Apr 1, 2019 · 13 comments · Fixed by scala/scala#7965
Closed

2.13: confusing error when using infix for nullary method #11461

lrytz opened this issue Apr 1, 2019 · 13 comments · Fixed by scala/scala#7965

Comments

@lrytz
Copy link
Member

lrytz commented Apr 1, 2019

In 2.12:

scala> class A { def foo() = 0 }
defined class A

scala> (new A) foo ()
res4: Int = 0

In 2.13:

scala> class A { def foo() = 0 }
defined class A

scala> (new A) foo ()
               ^
       error: no arguments allowed for nullary method foo: ()Int
@SethTisue SethTisue added this to the 2.13.1 milestone Apr 1, 2019
@som-snytt
Copy link

Why would you apply unit value to a method that takes no params? The message makes perfect sense if you have drunk no kool-aid.

If someone is confused, maybe -Xlint:defuse to detect the infix and unit value arg and nuance the message. Or just nuance for the case of unit and nullary method. a.f(()) would result in the same advice.

@ritschwumm
Copy link

how else would i call a nullary method like this in no-dots/dsl syntax?

@som-snytt
Copy link

@ritschwumm That is called postfix, not infix.

@ritschwumm
Copy link

calling def foo = 0 as obj foo would be postfix, which has been deprecated for a long time now.
calling def foo() = 0 as obj foo () always counted as infix.

@som-snytt
Copy link

That was a bug. The spec: "The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses...".

There is no deprecation, although the feature doc is persuasive: "Postfix notation is preserved for backward compatibility only. Historically, several DSLs written in Scala need the notation."

scala> object X { def f() = 42 }
defined object X

scala> X f ()
         ^
       error: no arguments allowed for nullary method f: ()Int

scala> X f
         ^
       error: postfix operator f needs to be enabled
       by making the implicit value scala.language.postfixOps visible.
       This can be achieved by adding the import clause 'import scala.language.postfixOps'
       or by setting the compiler option -language:postfixOps.
       See the Scaladoc for value scala.language.postfixOps for a discussion
       why the feature needs to be explicitly enabled.

scala> import scala.language.postfixOps
import scala.language.postfixOps

scala> X f
res3: Int = 42

scala> X.f
res4: Int = 42

scala> object X { def f(u: Unit*) = 42 }
defined object X

scala> X f
         ^
       error: missing argument list for method f in object X
       Unapplied methods are only converted to functions when a function type is expected.
       You can make this conversion explicit by writing `f _` or `f(_)` instead of `f`.

scala> X f ()
res6: Int = 42

@ritschwumm
Copy link

ritschwumm commented Apr 3, 2019

so dotless DSL syntax is effectively dead now, except when you are lucky and all methods involved take exactly one parameter in one parameter list? maybe it should be removed altogether then, simplifying the grammar some more...

@som-snytt
Copy link

Alternatively, someone could propose a new feature, "unit value discard," as vengeance for "value discard," to apply just for this case, discarding unit value when no value is expected in a param list. (Note that no value is not Nothing here.)

Meantime, the PR avoids advanced DSL gymnastics and simply suggests:

scala> object X { def f() = 42 }
defined object X

scala> X f ()
         ^
       error: can't supply unit value with infix notation because nullary method f: ()Int takes no arguments; use dotted invocation instead: X.f()

@som-snytt
Copy link

Unit value discard is proposed at scala/scala#7973

@Jasper-M
Copy link

Jasper-M commented Apr 9, 2019

If you want to design a DSL that allows you to write this, you still can:

scala> object X { def f(u: Unit) = 42 }
defined object X

scala> X f ()
res3: Int = 42

Only now it's actually consistent. Now only a b (c, d) should always mean a.b((c, d)) and we're done...

@lrytz
Copy link
Member Author

lrytz commented Apr 9, 2019

This made it to the news 😂 https://www.heise.de/developer/meldung/Programmiersprache-Scala-2-13-erweitert-das-Collection-Framework-4367522.html#nav_weitere__1

@SethTisue
Copy link
Member

SethTisue commented Apr 9, 2019

LOL

Som already improved the description on scala/scala#7684, I have improved the title and also made the change in dem Release-Notes auf GitHub 🇩🇪

@som-snytt
Copy link

I see the unimproved title was translated directly in the foreign press. Now I wish I had come up with a good pun for it. On gitter yesterday, I said, In loco parenthesis.

@SethTisue
Copy link
Member

so dotless DSL syntax is effectively dead now, except when you are lucky and all methods involved take exactly one parameter in one parameter list? maybe it should be removed altogether then, simplifying the grammar some more...

Scala 3 is headed that direction, see scala/scala3#4311 and the @infix/@alpha SIP

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

Successfully merging a pull request may close this issue.

5 participants