3

I have a compile error and I do not understand it.

case class Point(x: Int, y: Int)

trait Rectangular {

  def topLeft: Point
  def bottomRight: Point

  def left = topLeft().x //Compile error occurring here
  def right = bottomRight.x
  def width = right - left

  // any many more concrete geometric methods.
 }

I am getting a compile error on the line where the third method is defined, saying "Point does not take parameters".

But I thought that you can invoke a function that does not take parameters with or without the (). As topLeft is just a method that has no parameters and has a return type of Point.

Peter Neyens
  • 9,452
  • 21
  • 32
fulhamHead
  • 617
  • 1
  • 9
  • 20

1 Answers1

5

The difference is described in Scala documentation:

http://docs.scala-lang.org/style/method-invocation.html

Shortly, parenthesis is used to mark a method that has side-effects, so it's not allowed to call 0-arity (marked as) pure-method as side-effectful. See also: What is the rule for parenthesis in Scala method invocation?

It's also related to UAP (Uniform Access Principle) as method without () is interpreted as accessor, so you can implement it as a val:

trait A { def a: Int } //for some reason it works with parenthesis as well
class B extends A { val a: Int = 5 }

So here someBInstance.a vs someATypedInstance.a is better than someBInstance.a vs someATypedInstance.a()

Besides that, there is an example that explains why you can't use def f = ... with () - simply because () is also used as shortcut to call apply:

scala> class Z { def apply() = 5 }
defined class Z

scala> def f = new Z
f: Z

scala> f()
res87: Int = 5    
Community
  • 1
  • 1
dk14
  • 21,273
  • 4
  • 45
  • 81
  • As I understand your statement: `so it's not allowed to call pure-method as side-effectful`, I believe that it's mis-leading. The following works fine on the REPL - `def f(): Int = 55`. I take the word "not allowed" to mean that the compiler will enforce such a restriction. – Kevin Meredith Dec 28 '15 at 15:17
  • 1
    @KevinMeredith I've added "marked as" specially for you; however, I meant what I meant if you write `def f(): Int = 5` that means your method is side-effectful, even if your current implementation is not, because you probably know that this `f` might be overridden with something not pure – dk14 Dec 28 '15 at 15:22
  • Good point that marking a 0-arity `Unit`-returning method with `()` indicates side-effects (http://stackoverflow.com/a/7606214/409976 as a reference). My only point was (in case someone new to the language reads it) that it's simply a convention/style - the compiler does not enforce it. – Kevin Meredith Dec 28 '15 at 19:54
  • @KevinMeredith except the case OP is talking about. I mean if you've got `def f = 5` (pure-method) compiler **enforces** you to always call it as pure, you can't call it as side-effectful `f()` - ":27: error: Int does not take parameters". Or shortly "it's not allowed to **call** (marked as) pure-method as side-effectful." :)))) – dk14 Dec 29 '15 at 05:01
  • @KevinMeredith Btw, that is partially because scala uses `()` to call `apply` method as well, otherwise it would be hard to decide (in some cases like in my updated answer) how much `()` we need to call such method (but it could be solved with enforcing to use the whole `apply` in such cases, so it's probably is not a main reason) – dk14 Dec 29 '15 at 05:06