Getting rid of use-site method-call-parens-count?

But the UAP is something completely orthogonal to the problem discussed here.

I’m not so sure. Odersky went straight to a difficult question: should Scala treat methods without any arguments as “f()” or “f”? This is especially important for Java inter-op, because methods defined with Java must have a parameter list.

I believe, but could be wrong, that the current implementation of Scala’s solution to this question is what causes the problem lihaoyi demonstrated.

Of course. To reiterate, my position would be: when there is a parameter list, require an argument list (even if empty). When there is no parameter lists, don’t expect any argument lists (this is already the case in Scala). This solves the issue.
The reason it was not done this way was to make some calls to Java methods look better, but I agree with @gmethvin that most of the time Java interfaces already need wrappers to look good anyway.

1 Like

when there is a parameter list, require an argument list (even if empty). When there is no parameter lists, don’t expect any argument lists (this is already the case in Scala). This solves the issue.

I don’t think this is possible, since there is no bytecode difference between “def f” and “def f()”.

It’s already impossible to call def f as f(). So the compiler does know the difference.

There is. This kind of information is contained in the ScalaSignature attribute.

1 Like

I see. So it’s only the case where there is a parameter list that is a problem. Thanks for that.

The compiler knows the difference. The JVM does not.

Indeed, but the JVM doesn’t need to know. Unless you would want to be able to overload def f with def f().

1 Like

I suppose you are right.

As pointed out this would be a breaking change, however it gave me another idea.

toString is not “some unknown Java method.” Scala already knows about java.lang.Object and maps it specially to scala.Any and scala.AnyRef. When scala code calls toString it’s technically defined on scala.Any. Scala already has to handle it specially somewhat, e.g., for AnyVal. So it would not be a big deal for the SLS to say that toString is no-args.

Indeed. However, how bad is that? After all if a method is defined squarely in Java-land (as opposed to a “shared” type like Any/AnyRef/Object), one would expect it to look less idiomatic. It’s not that much different than the fact that when you use java.time you have to use x.plus(y) rather than x + y — Java APIs just aren’t scala-idiomatic.

2 Likes

This is also a breaking change, though. But it would probably be easy to make a scalafix rule for it.

Also, what should one do when calling toString on a Java class? And what about overriding it from a Java class?

To Scala all Java classes extend AnyRef which extends Any. To Java all Scala classes extend Object which extends nothing. I don’t think there’s a issue.

1 Like

I don’t think it’s an issue either, but at least there should be a special case in the Scala compiler when looking at a Java class C that overrides toString. If I’m not mistaken, Scala will consider this as a symbol of its own – if you call toString on a value statically known to be of this class, you won’t be calling AnyRef's toString, you will be calling C's toString. So scalac will need to ignore the parameter list or there will be an inconsistency.

Good point, so the SLS might have to say that Object.toString and (Java?) overrides are no-args. (If we go this ad-hoc route).
As long as we don’t detect Java pure methods, I might prefer the following route:

  • Java 0-parameter methods can be called with or without a parameter list (any rules are checked by a linter)
  • Scala 0-parameter methods can only be called as they are defined
  • To give the desired interaction, I’d allow Java 0-param methods to be overridden both with and without parameter list, but callers would have to conform to the Scala definition. So you can write override def toString and have to call it without arguments. (I’d rewrite override def toString() to override def toString with scalafix).

Remaining problem: Java methods can still be called inconsistently in this approach. If Java code is used enough for this to matter, I suspect I’d enforce consistency with style rules in some linter.

On the other hand, the ad-hoc solution for toString is “easier” (not sure it’s simpler). If toString is used so much more than other Java methods, maybe this ad-hoc solution is OK.

1 Like