I would like to know the difference between a variable passed by value, but lazy, and pass a variable by name in Scala.
I wrote this example to try to show but I do not, how should I do?
def callByValue(x : Unit) = {
x
x
}
def callByName(x : => Unit) = {
x
x
}
lazy val j = {println("initializing lazy"); 0}
var i = {println("initializing"); 0}
callByName(i = i + 1)
print(i + "\n") // "5"
callByValue(j)
print(j + "\n") // "1"
By "5" you mean, like, 2, right? And "1" means 0?
Is this one of those Google interview questions?
This shows the closure evaluated twice by the function:
scala> callByName {
| println("calling")
| i += 1
| }
calling
calling
and then
scala> println(i)
4
That's after it was 2.
HTH.
See if this helps.
val is executed at time of definition
lazy val is executed once
but at first time of reference
:=> pass by name is executed
everytime at time of reference but not at time of definition (think
of it like a function, a function is executed at time of
call/reference, not at time when we define a function),
def callByValue(x : Unit) = {
x
x
}
def callByName(x : => Unit) = {
x
x
}
val i = {println("i"); 0}//print should happen now at time of declaration. i is 0.
lazy val j = {println("j"); 0} //no print because {...} will get executed when j is referenced, not at time of definition.
val k = {println("k"); 0} //same as case of i, print should happen now. K should be 0
//no special case. A val being passed like a regular function
println("k test. K is val")
callByValue (k) //no prints as K block is already evaluated.
//passing a val to a function by name. The behavior will be same as K because i is already evaluated at time of definition. basically we are passing 0
println("i test. i is val but passed by Name.");
callByName(i);//I is passed by name. Thus the block will be executed everytime it is referenced
println("j test. It is passed lazy. It will be executed only once when referenced for 1st time")
callByValue(j) //prints j once, assigns value 0 to j inside callByValue function. Note that because j is lazy, it the block {print j;0} is evaluated once when j was referenced for first time. It is not executed everytime j was referenced.
println("test l")
callByName({println("l");0});//l is passed by name. Thus the block will be executed everytime it is referenced
println("test l again")
callByValue({println("l");0});//l is passed by value. Thus the block will be executed once
Output
i <- when i was defined. val i = {println("i"); 0}
k <- when k was defined. {println("k"); 0}
k test. K is val <- no further prints of 'k' as the {println("k"); 0} has already been evaluated
i test. i is val but passed by Name. <- no furhter prints of 'i' as {println("i"); 0} is already evaluated
j test. It is passed lazy. It will be executed only once when referenced for 1st time
j <- note j is printed now instead of time of definition
test l
l <- we passed {print(l);0}. It will get executed everytime l is referenced. Thus two prints corresponding to {x;x} code of call by name
l
test l again
l <- only one print when {print(l);0} was passed by value
Related
so, I am trying for loop in Scala. The code is below
val x = 5
for (x <- 1 until 10) {
println("the value is" + x)
}
The output is
the value is1
the value is2
the value is3
the value is4
the value is5
the value is6
the value is7
the value is8
the value is9
my question 1 is as it iterating thru the loop from 1 to 10. what is the use of x=5 then?
my question 2 is as far as understand in scala Val is immutable and var is mutable so why it is not throwing an error when the value x kept on changing?
Scala's for loop is syntactic sugar that desugars to the following (more or less):
val x = 5
(1 until 10).foreach { x =>
println("the value is" + x)
}
Which is (again essentially) equivalent to:
val x = 5
val myFunc: Int => Unit = { x =>
println("the value is" + x)
}
(1 until 10).foreach(myFunc)
This syntax makes it a little clearer that the x is a new variable that shadows the outer x in the new scope introduced by the function definition.
So in short, the two x variables are completely different because they have different scopes, and if you print x after the for loop, you'll still get 5.
not just in scala but in other programming languages as well local or inner variable precedes outer level(eg. class/ object) variable.
object VarlPrecedence {
val name = "object level"
def main(args: Array[String]): Unit = {
val name = "method level"
println(name)
}
}
output
method level
In your example, inner x is being used to iterate over the Range. Unlike you think the outer x is still immutable but unused.
loop is defined as below:
def loop : Boolean = loop
When x is defined as: def x = loop then "x: Boolean" is shown in console.
and
When x is defined as: val x = loop then it goes to infinite loop
I know def is using call by-name and val is using call by-value. Even though this point about loop defined above is not much clear.
def doesn't evaluate the right-hand side of the assignment. Just like
def f(x : Int) = x + 2
doesn't (in this case logically can't) evaluate f of anything, just defines what the function f, means, neither def loop : Boolean = loop nor def x = loop evaluate anything. You are just defining a function to be executed at some other point.
But vals do require the right-hand side of the assignment to be evaluated. So val x = loop tries to execute the expression on the right-hand side. Trying to evaluate loop never terminates, though, since loop is an infinite loop.
The call-by-name or call-by-value distinction seems less useful in this case, because neither your x, nor your loop take any arguments.
But there are two other ways in which val and def differ.
First distinction is: eager vs. lazy.
The right hand side of val is evaluated eagerly, as soon as the val is defined.
The right hand side of def is evaluated lazily, as soon as the
def is accessed.
For example:
def x = { println("x is evaluated"); 42 }
val y = { println("y is evaluated"); 42 }
x
Will print:
y is evaluated
x is evaluated
because y is evaluated immediately, whereas x is evaluated only when we call it.
The other difference is whether the result of the computation is cached or not:
The value of val is evaluated once, and then cached
The value of def is evaluated every time we call the function
This is why
def dice = { new scala.util.Random().nextInt(6) + 1 }
val once = { new scala.util.Random().nextInt(6) + 1 }
println(dice + " <-> " + once)
println(dice + " <-> " + once)
println(dice + " <-> " + once)
println(dice + " <-> " + once)
will output:
5 <-> 6
4 <-> 6
6 <-> 6
5 <-> 6
that is, dice is a more or less useful random number generator that generates values 1-6, whereas once is a rather useless random value that is fixed once it's created.
Now, you can think of a 2x2-table with eager-vs-lazy in one dimension, and cached-vs-not-cached on the other:
val is eager and cached
lazy val is lazy and cached (so are memoized defs)
def is lazy and uncached
There is not really eager and uncached, because computing something and then immediately throwing it away is not very useful. Maybe there is one exception that gets pretty close: the entry point of the program, because even though def main is a def, it always gets called anyway, so in a sense it's both kind-of eager and uncached.
In your code, loop is essentially a tail-recursive version of the non-terminating
def loop: Boolean = { while (true) {}; true }
but since loop is a def, and therefore lazy, the right hand side is not evaluated when you define it.
If you now define
def x = loop
nothing is happening still, because x is also lazy, so the right hand side is again not evaluated.
But if you define
val x = loop
then x is a val, thus its right hand side is evaluated eagerly. On the right hand side of the definition, there is an invocation of loop. Now loop is accessed, and since it is a def, it now evaluates its body, and goes into an infinite loop.
I'm trying to print out all the factors of every number in a list.
Here is my code:
def main(args: Array[String])
{
val list_of_numbers = List(1,4,6)
def get_factors(list_of_numbers:List[Int]) : Int =
{
return list_of_numbers.foreach{(1 to _).filter {divisor => _ % divisor == 0}}
}
println(get_factors(list_of_numbers));
}
I want the end result to contain a single list that will hold all the numbers which are factors of any of the numbers in the list. So the final result should be (1,2,3,4,6). Right now, I get the following error:
error: missing parameter type for expanded function ((x$1) => 1.to(x$1))
return list_of_numbers.foreach{(1 to _).filter {divisor => _ % divisor == 0}}
How can I fix this?
You can only use _ shorthand once in a function (except for some special cases), and even then not always.
Try spelling it out instead:
list_of_numbers.foreach { n =>
(1 to n).filter { divisor => n % divisor == 0 }
}
This will compile.
There are other problems with your code though.
foreach returns a Unit, but you are requiring an Int for example.
Perhaps, you wanted a .map rather than .foreach, but that would still be a List, not an Int.
A few things are wrong here.
First, foreach takes a function A => Unit as an argument, meaning that it's really just for causing side effects.
Second your use of _, you can use _ when the function uses each argument once.
Lastly your expected output seems to be getting rid of duplicates (1 is a factor for all 3 inputs, but it only appears once).
list_of_numbers flatMap { i => (1 to i) filter {i % _ == 0 }} distinct
will do what you are looking for.
flatMap takes a function from A => List[B] and produces a simple List[B] as output, list.distinct gets rid of the duplicates.
Actually, there are several problems with your code.
First, foreach is a method which yields Unit (like void in Java). You want to yield something so you should use a for comprehension.
Second, in your divisor-test function, you've specified both the unnamed parameter ("_") and the named parameter (divisor).
The third problem is that you expect the result to be Int (in the code) but List[Int] in your description.
The following code will do what you want (although it will repeat factors, so you might want to pass it through distinct before using the result):
def main(args: Array[String]) {
val list_of_numbers = List(1, 4, 6)
def get_factors(list_of_numbers: List[Int]) = for (n <- list_of_numbers; r = 1 to n; f <- r.filter(n%_ == 0)) yield f
println(get_factors(list_of_numbers))
}
Note that you need two generators ("<-") in the for comprehension in order that you end up with simply a List. If you instead implemented the filter part in the yield expression, you would get a List[List[Int]].
Recently I had an interview for Scala Developer position. I was asked such question
// matrix 100x100 (content unimportant)
val matrix = Seq.tabulate(100, 100) { case (x, y) => x + y }
// A
for {
row <- matrix
elem <- row
} print(elem)
// B
val func = print _
for {
row <- matrix
elem <- row
} func(elem)
and the question was: Which implementation, A or B, is more efficent?
We all know that for comprehensions can be translated to
// A
matrix.foreach(row => row.foreach(elem => print(elem)))
// B
matrix.foreach(row => row.foreach(func))
B can be written as matrix.foreach(row => row.foreach(print _))
Supposedly correct answer is B, because A will create function print 100 times more.
I have checked Language Specification but still fail to understand the answer. Can somebody explain this to me?
In short:
Example A is faster in theory, in practice you shouldn't be able to measure any difference though.
Long answer:
As you already found out
for {xs <- xxs; x <- xs} f(x)
is translated to
xxs.foreach(xs => xs.foreach(x => f(x)))
This is explained in §6.19 SLS:
A for loop
for ( p <- e; p' <- e' ... ) e''
where ... is a (possibly empty) sequence of generators, definitions, or guards, is translated to
e .foreach { case p => for ( p' <- e' ... ) e'' }
Now when one writes a function literal, one gets a new instance every time the function needs to be called (§6.23 SLS). This means that
xs.foreach(x => f(x))
is equivalent to
xs.foreach(new scala.Function1 { def apply(x: T) = f(x)})
When you introduce a local function type
val g = f _; xxs.foreach(xs => xs.foreach(x => g(x)))
you are not introducing an optimization because you still pass a function literal to foreach. In fact the code is slower because the inner foreach is translated to
xs.foreach(new scala.Function1 { def apply(x: T) = g.apply(x) })
where an additional call to the apply method of g happens. Though, you can optimize when you write
val g = f _; xxs.foreach(xs => xs.foreach(g))
because the inner foreach now is translated to
xs.foreach(g())
which means that the function g itself is passed to foreach.
This would mean that B is faster in theory, because no anonymous function needs to be created each time the body of the for comprehension is executed. However, the optimization mentioned above (that the function is directly passed to foreach) is not applied on for comprehensions, because as the spec says the translation includes the creation of function literals, therefore there are always unnecessary function objects created (here I must say that the compiler could optimize that as well, but it doesn't because optimization of for comprehensions is difficult and does still not happen in 2.11). All in all it means that A is more efficient but B would be more efficient if it is written without a for comprehension (and no function literal is created for the innermost function).
Nevertheless, all of these rules can only be applied in theory, because in practice there is the backend of scalac and the JVM itself which both can do optimizations - not to mention optimizations that are done by the CPU. Furthermore your example contains a syscall that is executed on every iteration - it is probably the most expensive operation here that outweighs everything else.
I'd agree with sschaef and say that A is the more efficient option.
Looking at the generated class files we get the following anonymous functions and their apply methods:
MethodA:
anonfun$2 -- row => row.foreach(new anonfun$2$$anonfun$1)
anonfun$2$$anonfun$1 -- elem => print(elem)
i.e. matrix.foreach(row => row.foreach(elem => print(elem)))
MethodB:
anonfun$3 -- x => print(x)
anonfun$4 -- row => row.foreach(new anonfun$4$$anonfun$2)
anonfun$4$$anonfun$2 -- elem => func(elem)
i.e. matrix.foreach(row => row.foreach(elem => func(elem)))
where func is just another indirection before calling to print. In addition func needs to be looked up, i.e. through a method call on an instance (this.func()) for each row.
So for Method B, 1 extra object is created (func) and there are # of elem additional function calls.
The most efficient option would be
matrix.foreach(row => row.foreach(func))
as this has the least number of objects created and does exactly as you would expect.
Benchmark
Summary
Method A is nearly 30% faster than method B.
Link to code: https://gist.github.com/ziggystar/490f693bc39d1396ef8d
Implementation Details
I added method C (two while loops) and D (fold, sum). I also increased the size of the matrix and used an IndexedSeq instead. Also I replaced the print with something less heavy (sum all entries).
Strangely the while construct is not the fastest. But if one uses Array instead of IndexedSeq it becomes the fastest by a large margin (factor 5, no boxing anymore). Using explicitly boxed integers, methods A, B, C are all equally fast. In particular they are faster by 50% compared to the implicitly boxed versions of A, B.
Results
A
4.907797735
4.369745787
4.375195012000001
4.7421321800000005
4.35150636
B
5.955951859000001
5.925475619
5.939570085000001
5.955592247
5.939672226000001
C
5.991946029
5.960122757000001
5.970733164
6.025532582
6.04999499
D
9.278486201
9.265983922
9.228320372
9.255641645
9.22281905
verify results
999000000
999000000
999000000
999000000
>$ scala -version
Scala code runner version 2.11.0 -- Copyright 2002-2013, LAMP/EPFL
Code excerpt
val matrix = IndexedSeq.tabulate(1000, 1000) { case (x, y) => x + y }
def variantA(): Int = {
var r = 0
for {
row <- matrix
elem <- row
}{
r += elem
}
r
}
def variantB(): Int = {
var r = 0
val f = (x:Int) => r += x
for {
row <- matrix
elem <- row
} f(elem)
r
}
def variantC(): Int = {
var r = 0
var i1 = 0
while(i1 < matrix.size){
var i2 = 0
val row = matrix(i1)
while(i2 < row.size){
r += row(i2)
i2 += 1
}
i1 += 1
}
r
}
def variantD(): Int = matrix.foldLeft(0)(_ + _.sum)
I'm a scala beginner and trying to understand how val works in Scala. I read that vals cannot be modified. When I do the following:
for( line <- Source.fromFile(args(0)).getLines() ) {
val currentLine = line
println(currentLine)
}
currentLine is updated in each iteration, while I expect it to be initialized with the first line and hold it till the end, or at least give a re-initialization error of some sort. Why is this so? Is the val created and destroyed in each iteration? My second question: I would like to use x outside if in the following code.
if( some condition is satisfied) val x = 2 else val x = 3
As of now, I'm getting an "Illegal start of simple expression" error. Is there a way to use x outside if?
Yes, the val is created and destroyed on each iteration.
val x = if(condition) 2 else 3 would do what you want.
Edit: You could rewrite 2. to if(conditon) {val x = 2} else {val x = 3} (to make it compile) but that would do nothing, since the if does not return anything and the variable can not be used outside the if
For Loop
You can break it down into a map operation.
for( line <- Source.fromFile(args(0)).getLines() ) {
val currentLine = line
println(currentLine)
}
So this code transforms to
Source.fromFile(args(0)).getLines().map( line => block )
block could be any expression. Where in your case block is:
{
val currentLine = line
println(currentLine)
}
Here currentLine is local to block and is created for each of the values of line given to map operation.
If-Else
Again following is also wrong:
if( some condition is satisfied) val x = 2 else val x = 3
Essentially if-else in Scala returns a value. So it should be:
if( condition ) expression1 else expression1
In your case you it can be:
if( condition ) { val x = 2 } else { val x = 3 }
However an assignment returns Unit ( or void if you want an analogy with Java / C++ ). So You can simply take the value of if-else like so:
val x = if( condition ) { 2 } else { 3 }
// OR
val x = if( condition ) 2 else 3
No answer mentioned it so in addition to what was said :
The val is made available for garbage collection on each iteration (and thus is not accessible from the next loop iteration). This is due to what is called scope of variables which is limited to the block in scala (same as Java).
As stated by #Kigyo val x = if(condition) 2 else 3 would do what you want, because you do only one assignation. If you put the assignation to val into the blocks, then the scope of this val is the block and thus not usable like you want to.
1st question: yes, in every iteration a new val is created
2nd question: you could rewrite it is
val x = if (some condition is satisfied)
2
else
3