Declaring multiple variables in Scala - 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.

Related

Updating a val in scala by reassigning

I am trying to update the value stored in a val in scala. I know i can't just directly do this like this: val x = 2; x = 1. This is not what I am doing, as I know you cannot reassign to a val. This is what I am trying to do:
val fp = List((1,2));
val fp = fp ::: List((1,3)); //hoping that x is List((1,2),(1,3))
But I get an message saying:
error: recursive value fp needs type
Also note, that I am restricted to using immutable data structures and vals only.
Any guidance would be appreciated
You can't reassign val in Scala. You should either use var:
var fp = List((1,2))
fp = fp ::: List((1,3))
Or use two vals:
val fp = List((1,2))
val fp2 = fp ::: List((1,3))
Usually you should try to avoid using vars, if you can. It makes your programs cleaner, and this way is surely more functional. So, I would prefer second option with two vals.
By the way, note, that you don't need to use semicolons. In fact, their usage in Scala is kind of discouraged.
In Scala, we encourage you to not reassign, as it creates undesirable side effects throughout your code, and makes it harder to reason about.
You need to get in the habit of throwing away variables and their mutations and starting to consider bindings of expressions. Var is considered bad form in Scala. As is reassignment. The following does exactly what you want, without any of the unwanted side effects vars and mutation would create:
val x = 2; val y = 1
If you needed to "mutate" x, then you could do something like the following:
val x = 2
val y = x + 2 // x = 2, y = 4
So that what you wanted from th fp would look like this:
val fp = List((1,2));
val fp1 = fp ::: List((1,3));

What does { val x = a; b.:::(x) } mean in Scala?

I am new to Scala and studying a book about it (Programming in Scala). I am really lost, what is the author trying to explain with the code below. Can anyone explain it in more detail ?
{ val x = a; b.:::(x) }
::: is a method that prepends list given as argument to the list it is called on
you could look at this as
val a = List(1, 2)
val b = List(3, 4)
val x = a
b.prependList(x)
but actually for single argument methods if it's not ambiguous scala allows to skip parenthesis and the dot and this is how this method is supposed to be used to not look ugly
x ::: b
it will just join these two lists, but there is some trick here
if method name ends with : it will be bound the other way
so typing x ::: b works as if this type of thing was done (x):::.b. You obviously can't type it like this in scala, won't compile, but this is what happens. Thanks to this x is on the left side of the operator and it's elements will be on the left side (beginning) of the list that is result of this call.
Oh well, now I found maybe some more explanation for you and also the very same piece of code you posted, in answer to this question: What good are right-associative methods in Scala?
Assuming a and b are lists: It assigns a to x, then returns the list b prepended with the list x.
For example, if val a = List(1,2,3) and val b = List(4,5,6) then it returns List(1,2,3,4,5,6).

issue `object Foo { val 1 = 2 }` in scala

I found this issue of scala: https://issues.scala-lang.org/browse/SI-4939
Seems we can define a method whose name is a number:
scala> object Foo { val 1 = 2 }
defined module Foo
But we can't invoke it:
scala> Foo.1
<console>:1: error: ';' expected but double literal found.
Foo.1
And we can invoke it inside the object:
scala> object O { val 1 = 1; def x = 1 }
defined module O
scala> O.x
res1: Int = 1
And follow will throw error:
scala> object O { val 1 = 2; def x = 1 }
defined module O
scala> O.x
scala.MatchError: 2
at O$.<init>(<console>:5)
at O$.<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
I use scalac -Xprint:typer to see the code, the val 1 = 2 part is:
<synthetic> private[this] val x$1: Unit = (2: Int(2) #unchecked) match {
case 1 => ()
}
From it, we can see the method name changed to x$1, and only can be invoked inside that object.
And the resolution of that issue is: Won't Fix
I want to know is there any reason to allow a number to be the name of a method? Is there any case we need to use a "number" method?
There is no name "1" being bound here. val 1 = 2 is a pattern-matching expression, in much the same way val (x,2) = (1,2) binds x to 1 (and would throw a MatchError if the second element were not thet same). It's allowed because there's no real reason to add a special case to forbid it; this way val pattern matching works (almost) exactly the same way as match pattern-matching.
There are usually two factors in this kind of decision:
There are many bugs in Scalac that are much higher priority, and bug fixing resources are limited. This behavior is benign and therefore low priority.
There's a long term cost to any increases in the complexity of the language specification, and the current behavior is consistent with the spec. Once things start getting special cased, there can be an avalanche effect.
It's some combination of these two.
Update. Here's what seems strange to me:
val pair = (1, 2)
object Foo
object Bar
val (1, 2) = pair // Pattern matching on constants 1 and 2
val (Foo, Bar) = pair // Pattern matching on stable ids Foo and Bar
val (foo, bar) = pair // Binds foo and bar because they are lowercase
val 1 = 1 // Pattern matching on constant 1
val Foo = 1 // *Not* pattern matching; binds Foo
If val 1 = 1 is pattern matching, then why should val Foo = 1 bind Foo rather than pattern match?
Update 2. Daniel Sobral pointed out that this is a special exception, and Martin Odersky recently wrote the same.
Here's a few examples to show how the LHS of an assignment is more than just a name:
val pair = (1, 2)
val (a1, b1) = pair // LHS of the = is a pattern
val (1, b2) = pair // okay, b2 is bound the the value 2
val (0, b3) = pair // MatchError, as 0 != 1
val a4 = 1 // okay, a4 is bound to the value 1
val 1 = 1 // okay, but useless, no names are bound
val a # 1 = 1 // well, we can bind a name to a pattern with #
val 1 = 0 // MatchError
As always, you can use backticks to escape the name. I see no problem in supporting such names – either you use them and they work for you or they do not work for you, and you don’t use them.

What is the accepted/recommended syntax for Scala code with lots of method-chaining?

In Scala I tend to favour writing large chained expressions over many smaller expressions with val assignments. At my company we've sort of evolved a style for this type of code. Here's a totally contrived example (idea is to show an expression with lots of chained calls):
import scala.util.Random
val table = (1 to 10) map { (Random.nextInt(100), _) } toMap
def foo: List[Int] =
(1 to 100)
.view
.map { _ + 3 }
.filter { _ > 10 }
.flatMap { table.get }
.take(3)
.toList
Daniel Spiewak's Scala Style Guide (pdf), which I generally like, suggests the leading dot notation in the chained method calls may be bad (see doc: Method Invocation / Higher-Order Functions), though it doesn't cover multi-line expressions like this directly.
Is there another, more accepted/idiomatic way to write the function foo above?
UPDATE: 28-Jun-2011
Lots of great answers and discussion below. There doesn't appear to be a 100% "you must do it this way" answer, so I'm going to accept the most popular answer by votes, which is currently the for comprehension approach. Personally, I think I'm going to stick with the leading-dot notation for now and accept the risks that come with it.
The example is slightly unrealistic, but for complex expressions, it's often far cleaner to use a comprehension:
def foo = {
val results = for {
x <- (1 to 100).view
y = x + 3 if y > 10
z <- table get y
} yield z
(results take 3).toList
}
The other advantage here is that you can name intermediate stages of the computation, and make it more self-documenting.
If brevity is your goal though, this can easily be made into a one-liner (the point-free style helps here):
def foo = (1 to 100).view.map{3+}.filter{10<}.flatMap{table.get}.take(3).toList
//or
def foo = ((1 to 100).view map {3+} filter {10<} flatMap {table.get} take 3).toList
and, as always, optimise your algorithm where possible:
def foo = ((1 to 100).view map {3+} filter {10<} flatMap {table.get} take 3).toList
def foo = ((4 to 103).view filter {10<} flatMap {table.get} take 3).toList
def foo = ((11 to 103).view flatMap {table.get} take 3).toList
I wrap the entire expression into a set of parenthesis to group things and avoid dots if possible,
def foo: List[Int] =
( (1 to 100).view
map { _ + 3 }
filter { _ > 10 }
flatMap { table.get }
take(3)
toList )
Here's how extempore does it. You can't go wrong.
(specMember
setInfo subst(env, specMember.info.asSeenFrom(owner.thisType, sym.owner))
setFlag (SPECIALIZED)
resetFlag (DEFERRED | CASEACCESSOR | ACCESSOR | LAZY)
)
Authentic compiler source!
I prefer lots of vals:
def foo = {
val range = (1 to 100).view
val mappedRange = range map { _+3 }
val importantValues = mappedRange filter { _ > 10 } flatMap { table.get }
(importantValues take 3).toList
}
Because I don't know what you want to purpose with your code, I chose random names for the vals.
There is a big advantage to choose vals instead of the other mentioned solutions:
It is obvious what your code does. In your example and in the solutions mentioned in most other answers anyone does not know at first sight what it does. There is too much information in one expression. Only in a for-expression, mentioned by #Kevin, it is possible to choose telling names but I don't like them because:
They need more lines of code
They are slower due to pattern match the declared values (I mentioned this here).
Just my opinion, but I think they look ugly
My rule: if the expression fits on a single (80-120 character) line, keep it on one line and omit the dots wherever possible:
def foo: List[Int] =
(1 to 100).view map { _ + 3 } filter { _ > 10 } flatMap table.get take 3 toList
As Kevin pointed out, the point-free style may improve brevity (but could harm readability for developers not familiar with it):
def foo: List[Int] =
(1 to 100).view map{3+} filter{10<} flatMap table.get take 3 toList
The leading dot notation is perfectly acceptable if you need to separate the expression over multiple lines due to length. Another reason to use this notation is when the operations need individual comments. If you need to spread an expression over multiple lines, due to its length or the need to comment individual operations, it's best to wrap the entire expression in parens (as Alex Boisvert suggests. In these situations, each (logical) operation should go on its own line (i.e. each operation goes on a single line, except where multiple consecutive operations can be described succinctly by a single comment):
def foo: List[Int] =
( (1 to 100).view
map { _ + 3 }
filter { _ > 10 }
flatMap table.get
take 3
toList )
This technique avoids potential semicolon inference issues that can arise when using leading dot notation or calling a 0-arg method at the end of the expression.
I usually try to avoid using dot for things like map and filter. So I would probably write it like the following:
def foo: List[Int] =
(1 to 100).view map { x =>
x + 3 } filter { x =>
x > 10 } flatMap { table.get } take(3) toList
The leading dot notation is very readable. I might start using that.

scala currying by nested functions or by multiple parameter lists

In Scala, I can define a function with two parameter lists.
def myAdd(x :Int)(y :Int) = x + y
This makes it easy to define a partially applied function.
val plusFive = myAdd(5) _
But, I can accomplish something similar by defining and returning a nested function.
def myOtherAdd(x :Int) = {
def f(y :Int) = x + y
f _
}
Cosmetically, I've moved the underscore, but this still feels like currying.
val otherPlusFive = myOtherAdd(5)
What criteria should I use to prefer one approach over the other?
There are at least four ways to accomplish the same thing:
def myAddA(x: Int, y: Int) = x + y
val plusFiveA: Int => Int = myAddA(5,_)
def myAddB(x: Int)(y : Int) = x + y
val plusFiveB = myAddB(5) _
def myAddC(x: Int) = (y: Int) => x + y
val plusFiveC = myAddC(5)
def myAddD(x: Int) = {
def innerD(y: Int) = x + y
innerD _
}
val plusFiveD = myAddD(5)
You might want to know which is most efficient or which is the best style (for some non-performance based measure of best).
As far as efficiency goes, it turns out that all four are essentially equivalent. The first two cases actually emit exactly the same bytecode; the JVM doesn't know anything about multiple parameter lists, so once the compiler figures it out (you need to help it with a type annotation on the case A), it's all the same under the hood. The third case is also extremely close, but since it promises up front to return a function and specifies it on the spot, it can avoid one internal field. The fourth case is pretty much the same as the first two in terms of work done; it just does the conversion to Function1 inside the method instead of outside.
In terms of style, I suggest that B and C are the best ways to go, depending on what you're doing. If your primary use case is to create a function, not to call in-place with both parameter lists, then use C, because it tells you what it's going to do. (This version is also particularly familiar to people coming from Haskell, for instance.) On the other hand, if you are mostly going to call it in place but will only occasionally curry it, then use B. Again, it says more clearly what it's expected to do.
You could also do this:
def yetAnotherAdd(x: Int) = x + (_: Int)
You should choose the API based on intention. The main reason in Scala to have multiple parameter lists is to help type inference. For instance:
def f[A](x: A)(f: A => A) = ...
f(5)(_ + 5)
One can also use it to have multiple varargs, but I have never seen code like that. And, of course, there's the need for the implicit parameter list, but that's pretty much another matter.
Now, there are many ways you can have functions returning functions, which is pretty much what currying does. You should use them if the API should be thought of as a function which returns a function.
I think it is difficult to get any more precise than this.
Another benefit of having a method return a function directly (instead of using partial application) is that it leads to much cleaner code when using infix notation, allowing you to avoid a bucketload of parentheses and underscores in more complex expressions.
Consider:
val list = List(1,2,3,4)
def add1(a: Int)(b: Int) = a + b
list map { add1(5) _ }
//versus
def add2(a: Int) = a + (_: Int)
list map add2(5)