3

I'm parsing some XML, and I'm chaining calls without a dot. All of these methods take no parameters (except \\, which takes one), so it should be fairly possible to chain them without a dot, right?

This is the code that does not work:

val angle = filteredContextAttributes.head \\ "contextValue" text toDouble

The error is: not found: value toDouble

However, it does work like this:

(filteredContextAttributes.head \\ "contextValue" text) toDouble

text returns only a String and does not take parameters, and I don't see any other parameters needed in \\ to cause an issue.

What am I missing? I don't want to hack it out, but to understand what' the problem.

And also I can't use head without the dot. When removing the dot it says: Cannot resolve symbol head

Aleksandar Stojadinovic
  • 4,851
  • 1
  • 34
  • 56

2 Answers2

3

It's because text is a postfix notation - this means a method follows the object and takes no parameters. The trick with postfix is that it can only appear at the end expression. That's why when you add parenthesis it works (the expression is then bounded by the parenthesis and you get two postfix notations, one ending with text and the second one ending with toDouble). In your example that's not the case as you are trying to call a method further in the chain.

That's also the reason why you need to do filteredContextAttributes.head and not filteredContextAttributes head. I'm sure if you do (filteredContextAttributes head) it will work as again the postfix notation will be at the end of the expression!

There are also prefix and infix notations in Scala and I urge you to read about them to get a hang of when you can skip . and () (for instance why you need () when using the map method etc.).

Mateusz Dymczyk
  • 14,969
  • 10
  • 59
  • 94
  • Just at the time you posted the answer I found this: http://stackoverflow.com/questions/1181533/what-are-the-precise-rules-for-when-you-can-omit-parenthesis-dots-braces-f . Somehow I feel it should be indexed better... Nevertheless, thank you very much! – Aleksandar Stojadinovic Aug 04 '15 at 13:17
  • @AleksandarStojadinovic oh that's an amazing answer, people definitely should read it :-) – Mateusz Dymczyk Aug 04 '15 at 13:26
2

To add on what @Mateusz already answered, this is the because of mixing postfix notation and arity-0 suffix notation.

There's also a great write up in another answer: https://stackoverflow.com/a/5597154/125901

You can even see a warning on your shorter example:

scala> filteredContextAttributes.head \\ "contextValue" text
<console>:10: warning: postfix operator text should 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 Scala docs for value scala.language.postfixOps for a discussion
why the feature should be explicitly enabled.

Which is a pretty subtle hint that this isn't the best construct style-wise. So, if you aren't specifically working in a DSL, then you should prefer adding in explicit dots and parenthesis, especially when mixing infix, postfix and/or suffix notations.

For example, you can prefer doc \\ "child" over doc.\\("child"), but once you step outside the DSL--in this example when you get your NodeSeq--prefer adding in perens.

Community
  • 1
  • 1
Chris Scott
  • 1,721
  • 14
  • 27