When working with the standard widget toolkit (SWT), I usually use something like this to define my GridLayout:
layout.marginTop = layout.marginBottom =
layout.marginLeft = layout.marginRight =
layout.horizontalSpacing = layout.verticalSpacing = 20
It works in java but not in scala.
It gives me type mismatch; Found: Unit Required: Int.
So how can this solve it?
You cannot do this in one line in scala because the result type of an assignment expression (e.g. a = b) is Unit. You'd have to have 6 separate calls:
layout.marginTop = 20
layout.marginBottom = 20
... etc
Why is the result type of an assignment Unit and nmot the assigned value? I believe this was chosen for performance reasons as outlined in this question.
There is a related question on assignment which points out that at declaration site, it is possible via:
val a, b, c = X
You have to write multiple assignments separately. As the compiler says, an assignment in Scala returns Unit, which can be seen as Java's void.
You could do
def assign[A](a:A)(fs: (A => Unit)*) = fs.foreach(_(a))
val r = new java.awt.Rectangle
assign(20)(r.x=_, r.y=_, r.width=_, r.height=_)
But this is clearly worse than writing everything separately. But at least you don't have to type "layout" every time in Scala:
val rectangle = new java.awt.Rectangle
import rectangle._
x = 20
y = 20
width = 20
height = 20
Related
I am always fascinated to see how scala always infers the type correctly . How scala does it?
scala> val num = 5
num: Int = 5
scala> val num = "5"
num: String = 5
I know it might be a very stupid question to ask here but i don't know the answer.
Please enlighten me.
Thanks!
There are several methods for inferencing the type of a variable. Mainly using those called inference rules based in logic theory.
There are plenty of papers explaining the theory behind. Here I put a good example (with Scala ;) )
www2.in.tum.de/hp/file?fid=879
While parsing the code compile can infer that 5 is of type Int and "5" is of String type.
In simple terms any value enclosed in double quotes " will be considered String, value enclosed in single quote ' is considered Char and digits are considered Int (unless specified otherwise).
This is further used to used to infer types for expression results.
Consider this example
val a = 5 // translates to val a:Int = 5
val b = "5" // translates to val b:String = "5"
val x = a+1 // expression 1
val y = b+1 // expression 2
In this example the code type of a is inferred as Int and type of b is inferred as String.
Based on this expression 1 calls function Int.+(x: Int): Int which returns Int, hence type of x is guessed to be Int.
Similarly expression 2 calls function StringOps.+(arg0: Any): String which returns String, hence type of y is guessed to be String.
I am trying to figure out if Scala programming language has a way of Aliasing(presence of two or more distinct referencing methods for the same memory location).
I can see example of type aliasing such as "x: (Int, String) = (1,one)". So x has two different types but do they share same memory?
I would greatly appreciate if anyone could give more explanation.
If you want one "variable" to track another, you could do something like this.
scala> var x = 5 // create a variable
x: Int = 5
scala> def y = x // keep track of x
y: Int
scala> x = 9 // change x
x: Int = 9
scala> y // yep, y changes too
res1: Int = 9
This isn't a true alias. You can't modify y and see the change in x. A def is simply re-evaluated every time it is invoked, so every time you query y, it re-examines x for the current value.
Note that this type of thing is not considered good Scala practice. In Functional Programming you want to avoid data structures that maintain state, i.e. don't use a var if you don't have to, and good Scala programmers almost never have to.
For most languages I wouldn't ask "why did they do X like this?" as it's generally opinion based.
For languages like C++ the usual answer is to quote some bit of some specification and all one can say is that someone probably thought long and hard before making a particular choice (but could have made a different choice).
Scala is different - often the answer is to point out that you can think of X in terms of some simpler structures Y and Z and so the formulation of X as it is makes sense when seen in this context.
So given that I'll ask why Scala allows a definitions that introduces multiple names and evaluates a given expression once for each name?
If you asked a Java programmer to guess what would happen here, they'd probably guess wrong:
var x, y, z = 3
I.e. they'd guess only z got assigned a value.
If you explained val and then told them the following was legal:
val x, y, z = 3
Then they'd probably guess more was afoot as clearly x and y must have values after this line as they cannot be assigned a different value later.
They might assume that x and y took a default values for their type, e.g. 0 for integers, but as there are no explicit types here that'd be a leap.
They might assume that it's handled as:
val z = 3
val x = z
val y = z
It doesn't really matter when the expression to the left of the = produces a primitive value or an immutable object. But the following might give them cause to wonder:
val x, y, z = new StringBuilder
Why would anyone want to introduce three names for the same StringBuilder instance?
And if you showed them the following they might, from the construction, guess that something odder was up before they even ran the code:
var i = 0
def f: Int = {
i += 1
println(i)
i
}
val x, y, z = f
One eventually realizes that the expression that appears to only be associated with z is actually evaluated once for each name, i.e. the above is equivalent to:
val x = f
val y = f
val z = f
So is it even interesting to talk about what programmers who are used to another language might think?
Well most people come to a language like Scala from somewhere else so to a degree constructions that are likely to be confusing should be avoided unless there's a good reason for them.
At first glance this feature doesn't seem to offer much, it avoids you having to repeat yourself, but to add this piece of rather confusing syntactical sugar for such a small gain seems odd.
So is there some circumstance in which it brings real benefit? Or is there no real gain here but e.g. we maintain some kind of logical consistency with some broader pattern established elsewhere?
There is one case where this surprising feature is used: when defining a scala.Enumeration:
object Weekday extends scala.Enumeration {
val Monday, Tuesday, Wednesday, Thursday, Friday = Value
}
which calls Value (a def inherited from Enumeration) 5 times, once for each field of the enumeration. Effectively this allocates a new instance of Enumeration#Value for each field, which is obviously what you need for an enumeration to be useful.
Without this multi-assignment feature, you would have to write:
object Weekday extends scala.Enumeration {
val Monday = Value
val Tuesday = Value
val Wednesday = Value
val Thursday = Value
val Friday = Value
}
I have never seen the multi-assignment feature used anywhere else but in an Enumeration declaration.
Whether or not this is good idea in terms of language design is a subjective question, and SO is not the right place to discuss it.
You have basically answered your own question. The choice is between val x, y, z = someComplexExpression meaning
val z = someComplexExpression
val y = z
val x = z
or
val x = someComplexExpression
val y = someComplexExpression
val z = someComplexExpression
or not being allowed at all. The first is a bad choice for two reasons:
You mention the first: you don't generally need to give multiple names to the same instance.
If you choose the first, you have to duplicate the someComplexExpression every time you need the second, or to extract it to a method. If you choose the second, writing the first when you need it (despite point 1) is trivial:
val z = someComplexExpression
val x, y = z
Not allowing it would be possible. I don't think I've ever actually seen it used [before seeing your comment]. But removing it once it's allowed is a bad idea.
Obviously var x, y, z = ... needs to be consistent with this.
I'm using Scala 2.11.2.
If I have this Fraction class:
case class Fraction(numerator: Int, denominator: Int) {}
Then this gives an error:
val f = new Fraction(numerator=-1, denominator=2)
But this is not:
val f = new Fraction(-1, denominator=2)
The error message is:
Multiple markers at this line
- not found: value
numerator
- not found: value
numerator
I tried to use negative numbers in other snippets with the same result, but the documentation doesn't mentions that this is not possible.
Am I doing something wrong?
Thanks
You need a space between the = and the -, or you can wrap the -1 in parentheses, otherwise the compiler gets confused. This is because =- is a valid method name, so the compiler cannot tell whether you are assigning a value to a named parameter, or making a method call.
so this gives an error:
val f = Fraction(numerator=-1, denominator=2)
but this is OK:
val f = Fraction(numerator = -1, denominator = 2)
and so is this:
val f = Fraction(numerator=(-1), denominator=2)
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.