10

Scala is an interesting language which claims to be concise, scalable (by having many features specified in libraries rather than the compiler), and to support DSLs. In trying to achieve this it has lots of operators plus compiler tweaks (e.g. to support infix operators and for example : _* to flatten a sequence).

I find the many operators (2½ pages in the 'Programming in Scala' index) and compiler tweaks confusing. To be fair many of the operators are conventional arithmetic/boolean operators borrowed from C et al).

I've been told that underpinning this there are a few basic syntactic rules, I think that if I knew these it would reduce my cognitive load.

Are there a few rules (and if so what are they) or am I doomed to have learn the many 'operator' methods and implicits in the libraries?

erac
  • 155
  • 7

3 Answers3

7

There are two ways to understand your question about operators:

  1. What are the rules that govern how operators are treated by the Scala compiler? (Language Rules)
  2. What are the rules that govern how operators are defined in libraries? (Operator Definitions)

Language Rules

There are rules indeed. I will let you determine whether you think there are "few" of them or not. As most things Scala, you can find them in the Language Reference, Section 6.12.

The most important bits:

  • The only accepted prefix operators are +, -, ! and ~.

  • Any method that takes no argument can be used as a postfix operator.

  • Any method that takes one argument can be used as an infix operator. The precedence of these operations however is subject to specific rules, presumably mostly so that arithmetic and other expressions are treated as one would expect. The precedence is determined by the first character of the operator/method name, and matches what you would expect from C or Java.

  • All infix operators are left-associative, except for the ones that end with :. Typical examples include :: and +:.

So four rules, basically. I encourage you to read the spec for more insight.

Operator Definitions

The choice of operator definitions is up to the library designer(s). The Scala collection library, for instance, uses a relatively small and consistent set of operators (++, --, **, +=, -=, ++=, --=, +:, etc.). Parser combinators come with a more exotic set, and some libraries can be completely impenetrable at first to the profane because of their custom operator definitions (sbt or Lift come to mind, although this is just my personal opinion).

This has been recognized as a source of potential problems and the Scala style guide has this to say about symbolic method names (custom operators):

Avoid! Despite the degree to which Scala facilitates this area of API design, the definition of methods with symbolic names should not be undertaken lightly, particularly when the symbols itself are non-standard (for example, >>#>>). As a general rule, symbolic method names have two valid use-cases:

  • Domain-specific languages (e.g. actor1 ! Msg)
  • Logically mathematical operations (e.g. a + b or c :: d)
Philippe
  • 9,582
  • 4
  • 39
  • 59
  • Thanks, this is a great summary & the sort of thing I was looking for! I've managed to avoid the Java Language Reference for 12 years and the 'etc.' on the list of collection operators is a bit worrying. Maybe this confirms my concern that Scala is a language for Computer Scientists ;-) – erac Nov 10 '12 at 20:25
1

Scala have no special treatment for operators

Extracted from the book "Programming in Scala 2ed"

Any method can be an operator

In Scala operators are not special language syntax: any method can be an operator. What makes a method an operator is how you use it. When you write “s.indexOf('o')”, indexOf is not an operator. But when you write “ s indexOf 'o' ”, indexOf is an operator, because you’re using it in operator notation.

I can't find the 2 1/2 pages in the index that you're referring to.

Scala operators are consistently available as methods defined on some object. This is consistent also with the fact that any value is represented as an object in scala, differing from java special legacy treatment for primitive types.

The scala underlying implementation can make use of primitives for performance gains at the bytecode level, but this is transparent for the end user.

Operators

So the rule here is simple: every operator is in fact a method defined on some type. The operator infix notation is just a matter of readability, e.g.

val sum = 1 + 2

reads much better than

val sum = 1.+(2)

This notation is also the base to build dsl with a "natural feel". The testing library ScalaSpecs gives a clear demonstration of this.

Special compiler rules

There is a limited number of "compiler tweaks", as you said, that are available for the aforementioned purpose of allowing clearer and more understandable code.

A relevant summary of those "tweaks" can found here

Community
  • 1
  • 1
pagoda_5b
  • 7,333
  • 1
  • 27
  • 40
  • Not entirely right. It does treat some operator specially for the purpose of preserving the precedence rules that we all got used to. `5 + 4 * 3` really is `5.+(4.*(3))`. See also the right-associative operators ending in `:`, such as `::` and `+:`. – Philippe Nov 10 '12 at 13:55
  • operator precedence is defined in the specification, also look [here](http://stackoverflow.com/questions/2922347/operator-precedence-in-scala). The associativity rule is within the summary I already mentioned – pagoda_5b Nov 10 '12 at 16:27
1

All the information is available on stackoverflow and in the spec.

Here is my recommendation on where to start:

  1. Learn how to parse succession of identifiers into operands and operators. See my answer When to use parenthesis in Scala infix notation on this topic.
  2. Remember enough of the operator precedence list. Personally, I just remember the ones for arithmetic +, -, *, /, that letters have the lowest precedence, and that weird unicode ones have the highest. For the rest, I add parenthesis or just guess that the precedence will "work out" as the DSL designer intended or like in Java.
  3. Learn the x :: xs and xs ::: ys operators for lists since they are so prevalent and associate to the right because they end with :.
  4. Optionally, if you are curious, have a cursory look at the section 6.12 Prefix, Infix, and Postfix Operations of the spec so that you'll know in some corner of your brain that there are specifics with respect with operator having = and prefix operators.

Finally, one last word of advice. Do not try to learn all operators, do not assume you should know all operator meanings to use the language effectively. That is unless you have learned other languages by reading and remembering the complete API.

Community
  • 1
  • 1
huynhjl
  • 41,520
  • 14
  • 105
  • 158