James Iry just mentioned something I'd never noticed before in #scala:
scala> def f(i: Int, x: Int) = i match { case `x` => println("x!"); case _ => println("nope") }
f: (i: Int,x: Int)Unit
scala> f(1, 1)
x!
scala> f(1, 2)
nope
That's one of those things that I'd idly wondered how to do, but hadn't had a use case so hadn't really gone looking. Good to know it's possible and simple... and more or less makes sense.
More or less. Actually, I guess I'm kind of glad that the following doesn't compile:
scala> def f(i: Int) = i match { case `yield` => println(`yield`) }
<console>:4: error: not found: value yield
def f(i: Int) = i match { case `yield` => println(`yield`) }
I can live with the restriction as not being able to use a reserved word for a variable on the lhs of a pattern match, though it does make for a weird inconsistency:
scala> val (`yield`, x) = (1, 1)
<console>:4: error: not found: value yield
val (`yield`, x) = (1, 1)
^
scala> val `yield` = 1
yield: Int = 1
Chalk up one more to the box of "pain points caused by using pattern matching for parallel assignment."
scala> def f(`yield` : Int) = 5 match { case `yield` => "yup"; case _ => "nope"}
ReplyDeletef: (yield: Int)java.lang.String
scala> f(5)
res14: java.lang.String = yup
Ha! A step towards Prolog's unification, almost, perhaps :)
ReplyDeleteHello!
ReplyDeleteWould be happy for a little background knowledge, why
this is possible :D
best regards
Anonymous, can you clarify your question?
ReplyDeleteHello,
ReplyDeleteI really trying to see why the case statement is matching the x :). Dont know why but I dont get it :)
best regards
Anonymous: Those are backquotes - in Scala, you ordinarily use backquotes to use what would otherwise be a reserved word as a legal identifier. Ordinarily, a bare token on the left hand side of the arrow in the case clause of a match expression denotes a variable to be bound; however, when you backquote that token it becomes a reference to a variable in the enclosing scope. Hence, in the first example the value of x within the function is 1, and the case evaluates as 1 == 1.
ReplyDeleteThere's no inconsistency at all ... did you even read the error messages? This works:
ReplyDeletescala> val `yield` = 1
yield: Int = 1
scala> val (`yield`, x) = (1, 1)
x: Int = 1
And of course this does not:
scala> val yield = 1
:1: error: illegal start of simple pattern
val yield = 1
^
scala> val (yield, x) = (1, 1)
:1: error: illegal start of simple pattern
val (yield, x) = (1, 1)
"however, when you backquote that token it becomes a reference to a variable in the enclosing scope"
ReplyDeleteJust as if it didn't start with a lowercase letter.
ianam: you'll notice that you defined `yield` in the REPL session *before* attempting the extraction from the tuple. Since such an identifier was defined in scope, then the pattern match succeeded; if you simply enter the second line as the *first* statement in a REPL session, it will not compile.
ReplyDeleteThe inconsistency lies in the fact that a backquoted variable in a pattern match will perform an equality check so long as such a variable is in scope (which is what it did in your session) *unless* the backquoted token is a keyword, in which case it does not cause a new variable to be defined in this context.