74

Where can I find a list of Scala's "magic" functions, such as apply, unapply, update, +=, etc.?

By magic-functions I mean functions which are used by some syntactic sugar of the compiler, for example

o.update(x,y) <=> o(x) = y 

I googled for some combination of scala magic and synonyms of functions, but I didn't find anything.

I'm not interested with the usage of magic functions in the standard library, but in which magic functions exists.

6 Answers 6

81

As far as I know:

Getters/setters related:

apply update identifier_= 

Pattern matching:

unapply unapplySeq 

For-comprehensions:

map flatMap filter withFilter foreach 

Prefixed operators:

unary_+ unary_- unary_! unary_~ 

Beyond that, any implicit from A to B. Scala will also convert A <op>= B into A = A <op> B, if the former operator isn't defined, "op" is not alphanumeric, and <op>= isn't !=, ==, <= or >=.

And I don't believe there's any single place where all of Scala's syntactic sugars are listed.

Sign up to request clarification or add additional context in comments.

7 Comments

You might want to add the unary_! etc. operators that were listed in one of the other posts, since this looks like the most exhaustive answer to the question here :)
What's identifier_=? Never seen that.
@StefanEndrullis Try this: object X { var _x = 0; def x_=(n: Int) { _x = n }; def x = _x }; X.x = 5; println(X.x)
@Daniel C. Sobral: Ah, OK, identifier was just meant to be a placeholder. Got it. Thanks.
There's also equals that is called by ==
|
17

In addition to update and apply, there are also a number of unary operators which (I believe) qualify as magical:

  • unary_+
  • unary_-
  • unary_!
  • unary_~

Add to that the regular infix/suffix operators (which can be almost anything) and you've got yourself the complete package.

You really should take a look at the Scala Language Specification. It is the only authoritative source on this stuff. It's not that hard to read (as long as you're comfortable with context-free grammars), and very easily searchable. The only thing it doesn't specify well is the XML support.

Comments

12

Sorry if it's not exactly answering your question, but my favorite WTF moment so far is @ as assignment operator inside pattern match. Thanks to soft copy of "Programming in Scala" I found out what it was pretty quickly.

Using @ we can bind any part of a pattern to a variable, and if the pattern match succeeds, the variable will capture the value of the sub-pattern. Here's the example from Programming in Scala (Section 15.2 - Variable Binding):

expr match { case UnOp("abs", e @ UnOp("abs", _)) => e case _ => } 

If the entire pattern match succeeds, then the portion that matched the UnOp("abs", _) part is made available as variable e.

And here's what Programming Scala says about it.

That link no longer works. Here is one that does.

1 Comment

Can you share with us what the @ operator does?
4

I'll also add _* for pattern matching on an arbitrary number of parameters like

case x: A(_*) 

And operator associativity rule, from Odersky-Spoon-Venners book:

The associativity of an operator in Scala is determined by its last character. As mentioned on <...>, any method that ends in a ‘:’ character is invoked on its right operand, passing in the left operand. Methods that end in any other character are the other way around. They are invoked on their left operand, passing in the right operand. So a * b yields a.*(b), but a ::: b yields b.:::(a).


Maybe we should also mention syntactic desugaring of for expressions which can be found here


And (of course!), alternative syntax for pairs

a -> b //converted to (a, b), where a and b are instances 

(as correctly pointed out, this one is just an implicit conversion done through a library, so it's probably not eligible, but I find it's a common puzzler for newcomers)


1 Comment

IIRC -> is just a library function.
4

I'd like to add that there is also a "magic" trait - scala.Dynamic:

A marker trait that enables dynamic invocations. Instances x of this trait allow method invocations x.meth(args) for arbitrary method names meth and argument lists args as well as field accesses x.field for arbitrary field names field.

If a call is not natively supported by x (i.e. if type checking fails), it is rewritten according to the following rules:

foo.method("blah") ~~> foo.applyDynamic("method")("blah") foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah")) foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2)) foo.field ~~> foo.selectDynamic("field") foo.varia = 10 ~~> foo.updateDynamic("varia")(10) foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13) foo.arr(10) ~~> foo.applyDynamic("arr")(10) 

As of Scala 2.10, defining direct or indirect subclasses of this trait is only possible if the language feature dynamics is enabled.

So you can do stuff like

import scala.language.dynamics object Dyn extends Dynamic { def applyDynamic(name: String)(a1: Int, a2: String) { println("Invoked " + name + " on (" + a1 + "," + a2 + ")"); } } Dyn.foo(3, "x"); Dyn.bar(3, "y"); 

Comments

3

They are defined in the Scala Language Specification. As far as I know, there are just three "magic" functions as you mentioned.

Scalas Getter and Setter may also relate to your "magic":

scala> class Magic { | private var x :Int = _ | override def toString = "Magic(%d)".format(x) | def member = x | def member_=(m :Int){ x = m } | } defined class Magic scala> val m = new Magic m: Magic = Magic(0) scala> m.member res14: Int = 0 scala> m.member = 100 scala> m res15: Magic = Magic(100) scala> m.member += 99 scala> m res17: Magic = Magic(199) 

3 Comments

If you could dig for me an evidence for that claim, you'll be answering my question ;-) I assumed it'll be in the specs, but finding them in it is not a fun job.
Scala Language Specification: 6.15 Assignments ... If x is a parameterless function defined in some template, and the same template contains a setter function x_= as member, then the assignment x = e is interpreted as the invocation x_=(e ) of that setter function. Analogously, an assignment f .x = e to a parameterless function x is interpreted as the invocation f .x_=(e ). An assignment f (args) = e with a function application to the left of the “=’ operator is interpreted as f .update(args, e ), i.e. the invocation of an update function defined by f .
I ment, evidence that there're no more.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.