KChaloux
KChaloux

Reputation: 4058

Is <- only accessible by the compiler

Scala's <- arrow seems a bit strange. Most operators are implemented somewhere in the source as a function, defined on a data type, either directly or implicitly. <- on the other hand only seems to unusable outside of a for comprehension, where it acts as a syntactic element used to signal the binding of a new variable in a monadic context (via map).

This is the only instance I can think of where Scala has an operator-looking syntactical element that is only usable in a specific context, and isn't an actual function.

Am I wrong about how <- works? Is it a special case symbol used just by the compiler, or is there some way a developer could use this behavior when writing their own code?

For example, would it be possible to write a macro to transform

forRange (i <- 0 to 10) { print(i) } 

into

{ var i = 0; while (i <= 10) { print(i) } }

instead of its standard map equivalent? As far as I can tell, any usage of i <- ... outside of a for context causes an exception due to referencing an unknown value.

Upvotes: 3

Views: 119

Answers (2)

flavian
flavian

Reputation: 28511

In short, yes <- is a reserved operator in Scala. It's a compiler thing.

Foreach

There is a strong distinction between foreach and for yield, but the syntax is only syntactic sugar, transformed at compile time.

for (i <- 1 to 10) { statement } expression is translated to:

Range.from(1, 10).foreach(..)

Multiple variables: for (i <- 1 to 10; y <- 2 to 100) {..} becomes:

Range.from(1, 10).foreach( el => {Range.from(2, 100).foreach(..)});

With all the variations given by:

for (x <- someList) = someList.foreach(..).

Put simply, they all get de-sugared to foreach statements. The specific foreach being called is given by the collection used.

For yield

The for yield syntax is sugar for flatMap and map. The stay in the monad rule applies here.

for (x <- someList) yield {..} gets translated to a someList.flatMap(..).

Chained operations become hierarchical chains of map/flatMap combos:

for { x <- someList; y <- SomeOtherList } yield {} becomes:

someList.flatMap(x => { y.flatMap(..) }); and so on.

The point

The point is that the <- operator is nothing more than syntactic sugar to make code more readable, but it always gets replaced at compile time.

To emphasize Rob's point

Rob makes excellent examples of other Scala syntactic sugar.

A context bound

package somepackage;
class Test[T : Manifest] {}

Is actually translated to:

class Test[T](implicit evidence: Manifest[T])

As proof, try to alias a type with a context bound:

type TestAlias[T : Manifest] = somepackage.Test // error, the : syntax can't be used.. It is perhaps easy to see how the : Manifest part is actually not a type a parameter.

It's just easier to type class Test[T : Manifest] rather than class Test[T](implicit evidence: Manifest[T].

Upvotes: 6

Rob Napier
Rob Napier

Reputation: 299565

The <- operator is a reserved word in the language (see the Scala Language Specification, page 4), but it isn't alone. => is also a reserved word rather than a function. (Also _, :, =, <:, <%, >:, #, and @.) So you couldn't create a function with that name. I don't believe you could adapt it the way you're suggesting, either (though perhaps someone more clever will know a way). You could create a function called `<-` (with surrounding back-ticks), but that would probably be more awkward than it deserves.

Upvotes: 2

Related Questions