is this supposed to happen?
scala> val myList = List(42)
myList: List[Int] = List(42)
scala> val s2 :: Nil = myList
s2: Int = 42
scala> val S2 :: Nil = myList
<console>:8: error: not found: value S2
val S2 :: Nil = myList
^
It appears to be case sensitive. Bug or 'feature'?
It is case-sensitive. In a match pattern, an identifier beginning with a capital letter (or quoted by backticks) is treated as a reference to a defined value, not as a new binding.
This catches a lot of people by surprise, and it isn't entirely obvious from reading the Scala language specification. The most relevant bits are “variable patterns” ...
A variable pattern x is a simple identifier which starts with a lower case letter. It matches any value, and binds the variable name to that value.
... and “stable identifier patterns”:
To resolve the syntactic overlap with a variable pattern, a stable identifier pattern may not be a simple name starting with a lower-case letter.
Related questions:
Why does pattern matching in Scala not work with variables?
Scala pattern matching with lowercase variable name
How to pattern match into an uppercase variable?
Feature :)
:: is a form of pattern matching. In Scala, variables beginning with lowercase are used for variables that should be bound by the match. Variables starting with uppercase (or enclosed in backticks) are used for existing variables that are used as part of the pattern to match.
Related
This fails to compile:
Array[Byte](...) match { case Array(0xFE.toByte, 0xFF.toByte, tail # _* ) => tail }
I can, however, compile this:
val FE = 0xFE.toByte
val FF = 0xFF.toByte
bytes match { Array( FE, FF, tail # _* ) => tail }
Why does the first case fail to compile but not the second case?
Matching as currently implemented in Scala does not allow you to generate expressions inside your match statement: you must either have an expression or a match, but not both.
So, if you assign the values before you get into the match, all you have is a stable identifier, and the match works. But unlike almost everywhere else in Scala, you can't substitute an expression like 0xFE.toByte for the val FE.
Type inference will work, so you could have written
xs match { case Array(-2, -1, tail) => tail }
since it knows from the type of xs that the literals -2 and -1 must be Byte values. But, otherwise, you often have to do just what you did: construct what you want to match to, and assign them to vals starting with an upper-case letter, and then use them in the match.
There is no exceedingly good reason why it must have been this way (though one does have to solve the problem of when to do variable assignment and when to test for equality and when to do another level of unapply), but this is the way it (presently) is.
Because what you see in the match is not a constructor but extractor. Extractors extracts data into variables provided. That is why the second case works - you provide variables there. By the way, you did not have to create them in advance.
More about extractors at http://docs.scala-lang.org/tutorials/tour/extractor-objects.html
I have a Scala list. I can destructure the list into some variables thus:
var a :: b :: tail = myList
a should be ("A1")
b should be ("B1")
tail should be ('empty)
However, I do not seem to be able to reuse the same variables for another destructuring:
a :: b :: tail = anotherList
a should be ("A2")
b should be ("B2")
tail should be ('empty)
The compiler tells me that it expected a semi-colon but found an equals sign. Why is this?
Is it impossible to use already-declared variables when destructuring? Am I doing something stupid?
Pattern extraction requires a case, val or var prefix or must occur within a for expression. Therefore, re-assigning the variables is not possible.
The Scala Language lists these cases in §§4.1 (values), 4.2 (variables), 6.19 (for-comprehensions) and 8.4 (pattern matching expressions)
I'm reviewing some Scala code trying to learn the language. Ran into a piece that looks like the following:
case x if x startsWith "+" =>
val s: Seq[Char] = x
s match {
case Seq('+', rest # _*) => r.subscribe(rest.toString){ m => }
}
In this case, what exactly is rest # _* doing? I understand this is a pattern match for a Sequence, but I'm not exactly understanding what that second parameter in the Sequence is supposed to do.
Was asked for more context so I added the code block I found this in.
If you have come across _* before in the form of applying a Seq as varargs to some method/constructor, eg:
val myList = List(args: _*)
then this is the "unapply" (more specifically, search for "unapplySeq") version of this: take the sequence and convert back to a "varargs", then assign the result to rest.
x # p matches the pattern p and binds the result of the whole match to x. This pattern matches a Seq containing '+' followed by any number (*) of unnamed elements (_) and binds rest to a Seq of those elements.
I've seen this kind of code on countless websites yet it doesn't seem to compile:
def foo(): (Int, Int) = {
(1, 2)
}
def main(args: Array[String]): Unit = {
val (I, O) = foo()
}
It fails on the marked line, reporting:
not found: value I
not found: value O
What might be the cause of this?
The problem is the use of upper case letters I and O in your pattern match. You should try to replace it by lowercase letters val (i, o) = foo(). The Scala Language Specification states that a value definition can be expanded to a pattern match. For example the definition val x :: xs = mylist expands to the following (cf. p. 39):
val x$ = mylist match { case x :: xs => {x, xs} }
val x = x$._1
val xs = x$._2
In your case, the value definition val (i, o) = foo() is expanded in a similar way. However, the language specification also states, that a pattern match contains lower case letters (cf. p. 114):
A variable pattern x is a simple identifier which starts with a lower
case letter.
As per Scala naming convention,
Method, Value and variable names should be in camelCase with the first
letter lower-case:
Your I, O are pattern variables. However, you have to use caution when defining them. By convention, Scala expects the pattern variables to start with a lowercase letter and
expects constants to start with an uppercase letter. So, the code will not compile.
In Scala 2.9.1, when I declare the package object for "com.sample.website"
com.sample
package object website {
val (CONST_1, CONST_2, CONST_3) = (1, 2, 3)
}
The compiler throws 3 errors like
not found: value CONST_1
Am I doing something wrong or am I simply not allowed to use pattern matching value declaration in package objects?
Check this linke How to pattern match into an uppercase variable?, pattern match doesn't work with uppercase variables.
You need to convert it lower case variables or do it seperate.
Pattern matching only binds to lower case variables, in all contexts.
val (A,B) = (1,2) // Checks that A==1 and B==2
val (a,b) = (1,2) // Sets a=1, b=2