2

I am confused when I first come across the following piece of code.

In the class Element, there are three function definitions.

Why height and width can use contents directly as a variable of Array[String]?

Is it because every function in Scala is an object or some other rule?

I come from C++ world, so the definition really puzzles me.

abstract class Element {
  def contents: Array[String]
  def height: Int = contents.length
  def width: Int = if (height == 0) 0 else contents(0).length
}
Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
jerry
  • 355
  • 1
  • 6
  • 13
  • 2
    I didn't notice this on the first reading of your question, but it's worth pointing out that there are actually *no functions* in the `Element` class as written. There are three *methods*. A (nearly) equivalent *function* for the `contents` method would be declared as `val contents: () => Array[String]`. See [Difference between method and function in Scala](http://stackoverflow.com/questions/2529184/difference-between-method-and-function-in-scala) and the blog posts linked from that question to understand why this distinction matters. – Aaron Novstrup Sep 17 '12 at 07:34

2 Answers2

6

This is just syntax. The expression contents.length, for example, is compiled into a call of the contents method followed by a call of the length method on the result.

In general, parentheses can be omitted on zero-argument method calls. In fact, parentheses must be omitted when calling methods, such as your contents method, that have no parameter list in their definitions.

Note that this feature is part of Scala's commitment to the uniform access principle. The contents method could be replaced with a contents property without breaking callers.

Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
  • Thanks for the answer. But I think that "parentheses must be omitted on methods such as the contents method with no parameter list." is not entirely right. What about println()? I read this in Programming in Scala that it is better to not drop () in println() because of "side effect". – jerry Sep 17 '12 at 04:57
  • I'll clarify my answer -- I'm referring to methods that have no parameter list, not to methods (like println) that accept a variable number (including 0) of arguments. – Aaron Novstrup Sep 17 '12 at 05:00
  • I also added a note about the "uniform access principle", which is important to understanding much of Scala's design/conventions – Aaron Novstrup Sep 17 '12 at 05:06
  • 1
    @PéterTörök There's not anything to take sides about. The fact is that you *can not* legally use parentheses when calling a method that is defined with no parameter list (try it!). It's certainly true that such methods should be reserved for pure methods, but the language does not enforce that convention. – Aaron Novstrup Sep 17 '12 at 11:37
  • You are right, I did not read carefully enough, sorry :-( You were talking about function *calls* while I was talking about function *definitions*. I remove my comment above to avoid further confusion. – Péter Török Sep 17 '12 at 15:30
  • @PéterTörök That's okay, I appreciate your comment. I realized on retrospect that my answer didn't make it clear that I was referring to the parens on method calls, which may have led to jerry's confusion in the first place. – Aaron Novstrup Sep 17 '12 at 16:06
2

Nothing very special is going on. Compared to C++, you're hitting the follownig differences:

  • invocation of methods without arguments in Scala doesn't need parentheses - length in this case is the same as length()
  • method definitions don't need to be wrapped in {} if they contain only one expression
  • functions return the value of the last expression in their body

A more C/Java like way to write this would be

def height() : Int = { return contents.length(); } 

which would do the same, but be much more verbose - a nice demonstration of why Scala is an awesome language for reading code.

themel
  • 8,825
  • 2
  • 32
  • 31