Scala package object - val declaration - scala

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

Related

Scala - Cannot resolve symbol - Looping through map

I am doing programming in scala for looping through map.
Below is my code which works fine.
val names = Map("fname" -> "Robert", "lname" -> "Goren")
for((k,v) <- names ) println(s"Key: $k, Value : $v")
When looping through the map, if I give (K,V) instead of (k,v), the program is not compiling. It gives cannot resolve symbol error.
Below is my for loop -
for((K,V) <- names ) println(s"Key: $K, Value : $V")
I am executing this program in IntelliJ IDEA 15 scala worksheet.
Can anyone please explain the reason for this error.
It doesn't compile for the same reason this code doesn't compile:
val (A,B) = (1,2)
// error: not found: value A
// error: not found: value B
but this does compile:
val (a,b) = (1,2)
// a: Int = 1
// b: Int = 2
Constant names should be in upper camel case. That is, if the member
is final, immutable and it belongs to a package object or an object,
it may be considered a constant
Method, Value and variable names should be in lower camel case
Source: http://docs.scala-lang.org/style/naming-conventions.html

Scala syntax strangeness with :: and requiring lower case

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.

How can I find the definition of methods/operations defined in an implicitly-converted class?

I'm looking at someone else's source code (Scala), where I see the operator :+= being called on a variable of type IndexedSeq. I am looking all over the scaladocs page for that class to figure out what that operator does, but I do not see it. I'm thinking that either it's defined in a class outside of IndexedSeq's inheritance hierarchy, or else the javascript on the scaladocs page is hiding it somewhere I can't see it. (Actually it's neither; see answer below.)
I've hit every button on the scaladocs page trying to unhide everything. I've looked in the web-page's HTML code. There has got to be a way to look up an operator from the documentation of a class to which it can be applied. Hasn't there?
(N.B.: I looked up that operator using symbolhound, so I know what that operator means now. This question is about scala documentation in general, not that particular operator.)
All operators in Scala are normal methods.
You cannot find it because it is compiler magic for re-assignement, it is not an operator. Or to say it another way: it looks like an operator of its own, but it is actually "an operator followed by the = character".
The compiler will magically turn that into a assignment if the operator (here :+) returns the proper type, and the original value was a var, obviously.
Since it is not provided by any implicit nor explicit method on Seq[T] or whatever, it does not appear anywhere in the generated scaladoc.
So to answer the general question:
It is a language construct, so the only place where it is documented is the specification, sadly,
but, if you find some "<?>=" unknown operator somewhere, look for the definition of "<?>", that one is sure to be documented.
Edit: I finally found where this is defined in the SLS:
§6.12.4:
An assignment operator is an operator symbol (syntax category op in (§1.1)) that
ends in an equals character “=”, with the exception of operators for which one of the
following conditions holds:
(1) the operator also starts with an equals character, or
(2) the operator is one of (<=), (>=), (!=).
It also says later on that it only happens when all other options have been tried (including potential implicits).
Is this value assigned to a variable? If it's the case I think this syntax sugar:
scala> var x = IndexedSeq(1,2,3)
x: IndexedSeq[Int] = Vector(1, 2, 3)
scala> x :+= 10
scala> x
res59: IndexedSeq[Int] = Vector(1, 2, 3, 10)
scala> val y = IndexedSeq(1,2,3)
y: IndexedSeq[Int] = Vector(1, 2, 3)
scala> y :+= 10
<console>:16: error: value :+= is not a member of IndexedSeq[Int]
y :+= 10
^
It is syntax sugar for "operation and assignment", like +=:
scala> var x = 10
x: Int = 10
scala> x += 1
scala> x
res63: Int = 11
Which de-sugars to x = x + 1.

Scala not found: value x when unpacking returned tuple

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.

Declaring multiple variables in Scala

I'd like to use val to declare multiple variable like this:
val a = 1, b = 2, c = 3
But for whatever reason, it's a syntax error, so I ended up using either:
val a = 1
val b = 2
val c = 3
or
val a = 1; val b = 2; val c = 3;
I personally find both options overly verbose and kind of ugly.
Is there a better option?
Also, I know Scala is very well thought-out language, so why isn't the val a = 1, b = 2, c = 3 syntax allowed?
The trivial answer is to declare them as tuples:
val (a, b, c) = (1, 2, 3)
What might be interesting here is that this is based on pattern matching. What is actually happens is that you are constructing a tuple, and then, through pattern matching, assigning values to a, b and c.
Let's consider some other pattern matching examples to explore this a bit further:
val DatePattern = """(\d{4})-(\d\d)-(\d\d)""".r
val DatePattern(year, month, day) = "2009-12-30"
val List(rnd1, rnd2, rnd3) = List.fill(3)(scala.util.Random.nextInt(100))
val head :: tail = List.range(1, 10)
object ToInt {
def unapply(s: String) = try {
Some(s.toInt)
} catch {
case _ => None
}
}
val DatePattern(ToInt(year), ToInt(month), ToInt(day)) = "2010-01-01"
Just as a side note, the rnd example, in particular, may be written more simply, and without illustrating pattern matching, as shown below.
val rnd1, rnd2, rnd3 = scala.util.Random.nextInt(100)
Daniel's answer nicely sums up the correct way to do this, as well as why it works. Since he already covered that angle, I'll attempt to answer your broader question (regarding language design)...
Wherever possible, Scala strives to avoid adding language features in favor of handling things through existing mechanisms. For example, Scala doesn't include a break statement. However, it's almost trivial to roll one of your own as a library:
case object BreakException extends RuntimeException
def break = throw BreakException
def breakable(body: =>Unit) = try {
body
} catch {
case BreakException => ()
}
This can be used in the following way:
breakable {
while (true) {
if (atTheEnd) {
break
}
// do something normally
}
}
(note: this is included in the standard library for Scala 2.8)
Multiple assignment syntaxes such as are allowed by languages like Ruby (e.g. x = 1, y = 2, z = 3) fall into the category of "redundant syntax". When Scala already has a feature which enables a particular pattern, it avoids adding a new feature just to handle a special case of that pattern. In this case, Scala already has pattern matching (a general feature) which can be used to handle multiple assignment (by using the tuple trick outlined in other answers). There is no need for it to handle that particular special case in a separate way.
On a slightly different aside, it's worth noting that C's (and thus, Java's) multiple assignment syntax is also a special case of another, more general feature. Consider:
int x = y = z = 1;
This exploits the fact that assignment returns the value assigned in C-derivative languages (as well as the fact that assignment is right-associative). This is not the case in Scala. In Scala, assignment returns Unit. While this does have some annoying drawbacks, it is more theoretically valid as it emphasizes the side-effecting nature of assignment directly in its type.
I'll add one quirk here, because it hit myself and might help others.
When using pattern matching, s.a. in declaring multiple variables, don't use Capital names for the variables. They are treated as names of classes in pattern matching, and it applies here as well.
val (A,B)= (10,20) // won't work
println(A)
Error message does not really tell what's going on:
src/xxx.scala:6: error: not found: value A
val (A,B)= (10,20)
^
src/xxx.scala:6: error: not found: value B
val (A,B)= (10,20)
^
src/xxx.scala:7: error: not found: value A
println(A)
^
I thought `-ticking would solve the issue but for some reason does not seem to (not sure, why not):
val (`A`,`B`)= (10,20)
println(A)
Still the same errors even with that.
Please comment if you know how to use tuple-initialization pattern with capital variable names.
If all your variables are of the same type and take same initial value, you could do this.
val a, b, c: Int = 0;
It seems to work if you declare them in a tuple
scala> val (y, z, e) = (1, 2, 45)
y: Int = 1
z: Int = 2
e: Int = 45
scala> e
res1: Int = 45
Although I would probably go for individual statements. To me this looks clearer:
val y = 1
val z = 2
val e = 45
especially if the variables are meaningfully named.