Difference between def and val in Scala - scala

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.

Related

Is the map generator from the EPFL online course able to generate every possible map?

https://www.coursera.org/learn/progfun2 assignment for Week 1 shows, as an example, a generator for maps of type Map[Int, Int]:
lazy val genMap: Gen[Map[Int,Int]] = oneOf(
const(Map.empty[Int,Int]),
for {
k <- arbitrary[Int]
v <- arbitrary[Int]
m <- oneOf(const(Map.empty[Int,Int]), genMap)
} yield m.updated(k, v)
)
I'm new to Scala, but I'm familiar with generators in imperative programming languages. My understanding of the generator's execution flow is as follows:
arbitrary[Int] is called, it returns a generator yielding an endless sequence of Ints, the first generated value is assigned to k
arbitrary[Int] is called again, it returns a new generator, the first generated value is assigned to v
A random map is created recursively, updated with k->v, and yielded to the consumer
When the next value from the generator is requested, the execution resumes at m <- ... definition, proceeding with a new random m and the same k->v mapping
Neither const nor the recursive genMap ever run out of values, meaning that the "loop" for m never terminates, so new values for v and k are never requested from the corresponding arbitrary generators.
My conclusion is that all generated maps would either be empty or include the k->v mapping generated in the first iteration of the outermost invocation, i.e. genMap can never generate a non-empty map without such a mapping.
Q1: are my analysis and my conclusion correct?
Q2: if they are, how can I implement a generator which, after generating a first map, would have non-zero chance of generating any possible map?
Q3: if I simplify the last definition in the for-expression to m <- genMap, does that change the generator's behaviour in any way?
In short, your analysis and conclusion aren't correct.
I suspect the root of the misunderstanding is in interpreting for as a loop (it's not in general, and specifically not so in this context (when dealing with things that are more explicitly collections, for is close enough, I guess)).
I'll explain from the top down.
oneOf, given 1 or more generators will create a generator which, when asked to generate a value, will defer to one of the the given generators by random selection. So
oneOf(
const(Map.empty[Int, Int]),
k: Gen[Map[Int, Int]] // i.e. some generator for Map[Int, Int]
)
The output might be
someMapFromK, Map.empty, someMapFromK, someMapFromK, Map.empty, Map.empty...
In this case, our k is
for {
k <- arbitrary[Int]
v <- arbitrary[Int]
m <- oneOf(const(Map.empty[Int, Int]), genMap) // genMap being the name the outermost generator will be bound to
} yield m.updated(k)
for is syntactic sugar for calls to flatMap and map:
arbitrary[Int].flatMap { k =>
arbitrary[Int].flatMap { v =>
oneOf(const(Map.empty[Int, Int]), genMap).map { m =>
m.updated(k, v)
}
}
}
For something like List, map and flatMap consume the entire collection. Gen is lazier:
flatMap basically means generate a value, and feed that value to a function that results in a Gen
map basically means generate a value, and transform it
If we imagined a method on Gen named sample which gave us the "next" generated value (for this purpose, we'll say that for a Gen[T] it will result in T and never throw an exception, etc.) genMap is exactly analogous to:
trait SimpleGen[T] { def sample: T }
lazy val genMap: SimpleGen[Map[Int, Int]] = new SimpleGen[Map[Int, Int]] {
def sample: Map[Int, Int] =
if (scala.util.Random.nextBoolean) Map.empty
else {
val k = arbitrary[Int].sample
val v = arbitrary[Int].sample
val m =
if (scala.util.Random.nextBoolean) Map.empty
else genMap.sample // Since genMap is lazy, we can recurse
m.updated(k, v)
}
}
Regarding the third question, in the original definition, the extra oneOf serves to bound the recursion depth to prevent the stack from being blown. For that definition, there's a 1/4 chance of going recursive, while replacing the inner oneOf with genMap would have a 1/2 chance of going recursive. Thus (ignoring the chance of a collision in the ks), for the first:
50% chance of empty (50% chance of 1+)
37.5% chance of size 1 (12.5% chance of 2+)
9.375% chance of size 2 (3.125% chance of 3+)
2.34375 chance of size 3 (0.78125% chance of 4+)...
While for the second:
50% chance of empty
25% chance of size 1
12.5% chance of size 2
6.25% chance of size 3...
Technically the possibility of stack overflow implies that depending on how many recursions you can make there's a maximum number of k -> v pairs in the Map you can generate, so there are almost certainly Maps that could not be generated.

How reduceLeft works on sequence of Functions returning Future

This might be a naive question and I am sorry for that. I am studying Scala Futures and stumbled on below code:
object Main extends App {
def await[T](f: Future[T]) = Await.result(f, 10.seconds)
def f(n: Int): Future[Int] = Future {n + 1}
def g(n: Int): Future[Int] = Future {n * 2}
def h(n: Int): Future[Int] = Future {n - 1}
def doAllInOrder[T](f: (T => Future[T])*): T => Future[T] = {
f.reduceLeft((a,b) => x => a(x).flatMap(y => b(y)))
}
println(await(doAllInOrder(f, g, h)(10))) // 21
}
I know how reduceLeft works when it is applied on Collections. But in the above example, as I understand, in the first pass of reduceLeft value x i.e. 10 is applied to Function a and the result is applied to Function b using flatMap which eventually return Future[Int] (say, I call it result). In the next pass of reduceLeft the result and Function h has to be used, but here is I am troubled.
The result is actually an already executed Future, but the reduceLeft next pass expects a Function which returns a Future[Int].Then how it is working?
Another thing I am not able to understand how each pass sending its result to next pass of reduceLeft, i.e. how x is getting it's value in subsequent passes.
Though both of my confusions are interrelated and a good explanation may help clear my doubt.
Thanks in advance.
You have to think about reduceLeft to be independent from Future execution. reduceLeft creates a new function by combining two given ones and that's it.
reduceLeft is applied to a Seq of T => Future[T]. So, it's just simple iteration from left to right over sequence of functions taking first and second elements and reducing it to one single value, reducing this value with the 3rd element and so on. Eventually, having just two element left that are reduced to a single one.
The result of reduceLeft has to be of the same type as the type of elements in the collection. In your case, it's function T => Future[T].
Let's understand what (a,b) => x => a(x).flatMap(y => b(y)) is doing
This means the following. Given functions a and b, create a function that combines function a with b. Mathematically it's c(x)=b(a(x)).
Now, a and b are functions returning futures. And futures can be chained with the help of map/flatMap methods.
You should read x => a(x).flatMap(y => b(y)) as
Given an input x, apply function a(x), this results in a Future, when this future is completed, take result y and apply function b(y), this results in a new Future. This is the result of function c.
Note: value x is Int at all times. It is the input parameter for your new reduced function.
If it's still not clear, let's address the points of confusions
The result is actually an already executed Future.
No future is guaranteed to be executed at any point here. map and flatMap are non blocking operation and it applies functions to a Future. The result of this application is still a Future.
Another thing I am not able to understand how each pass sending its
result to next pass of reduceLeft, i.e. how x is getting it's value in
subsequent passes.
This is easier to understand when just having integers in a collection. Given following code
Seq(1, 2, 5, 10).reduceLeft(_ - _)
It will take 1, 2 and apply - function, this will result in -1. It will then combine -1 and 5 resulting in -6. And finally, -6 with 10 resulting in -16.

what is the use of assigning a value to a variable outside the for loop in scala

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.

Call-by-value and by-name equivalence

I'm working in a Coursera course on functional programming and at some point they discuss the difference between call-by-value and call-by-name evaluation techniques. They're some point that confuses me, they say:
Both techniques reduce to the same final values as long as:
the reduced expressions consists of pure functions and
both evaluations terminate
which seems to be a lambda calculus theorem.
Could you explain me what they mean by "the reduced expressions conssist of pure functions"?
A pure function is one which has no side-effects (such as doing IO or changing any value not local to the function). An example of a pure function would be:
def inc(x: Int) = x+1
An example of an impure function would be:
var sum = 1
def addToSum(x: Int) = {
sum += x
sum
}
So now let's consider the following two methods, which only differ by whether they take their arguments by name or value:
def doubleByValue(x: Int) = x + x
def doubleByName(x: =>Int) = x + x
Now if we use both of these with the pure function, the result is the same:
doubleByValue(inc(2)) // => 6
doubleByName(inc(2)) // => 6
But if we apply them to the impure function, the result differs:
sum = 1 // Let's reset sum, so the result isn't affected by previous uses
doubleByValue(addToSum(2)) // => 6, the value of `sum` is now 3
sum = 1 // Let's reset sum, so the result isn't affected by previous uses
doubleByName(addToSum(2)) // => 8, the value of `sum` is now 5
The difference is that the ByName version calls the function twice and adds the two results, whereas the ByValue version calls it once, saves the result and adds it to itself.
For the pure function this makes absolutely no difference - given the same argument, it will always return the same result, so it makes no difference whether you call it once and use the saved result twice or you call it twice (except for performance).
For the impure function it makes a big difference as the value of the sum variable is changed each time the function is called.

When does Scala force a stream value?

I am comfortable with streams, but I admit I am puzzled by this behavior:
import collection.immutable.Stream
object StreamForceTest extends App {
println("Computing fibs")
val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #::
fibs.zip(fibs.tail).map((x: (BigInt, BigInt)) => {
println("Adding " + x._1 + " and " + x._2);
x._1 + x._2
})
println("Taking first 5 elements")
val fibs5 = fibs.take(5)
println("Computing length of that prefix")
println("fibs5.length = " + fibs5.length)
}
with output
Computing fibs
Taking first 5 elements
Computing length of that prefix
Adding 0 and 1
Adding 1 and 1
Adding 1 and 2
fibs5.length = 5
Why should take(5) not force the stream's values to be computed,
while length does do so? Offhand neither one needs to actually
look at the values, but I would have thought that take was more
likely to do it than length. Inspecting the source code on github,
we find these definitions for take (including an illuminating
comment):
override def take(n: Int): Stream[A] = (
// Note that the n == 1 condition appears redundant but is not.
// It prevents "tail" from being referenced (and its head being evaluated)
// when obtaining the last element of the result. Such are the challenges
// of working with a lazy-but-not-really sequence.
if (n <= 0 || isEmpty) Stream.empty
else if (n == 1) cons(head, Stream.empty)
else cons(head, tail take n-1)
)
and length:
override def length: Int = {
var len = 0
var left = this
while (!left.isEmpty) {
len += 1
left = left.tail
}
len
}
The definition of head and tail is obtained from the specific
subclass (Empty and Cons). (Of course Empty is an object, not a
class, and its definitions of head and tail just throw
exceptions.) There are subtleties, but they seem to concern making
sure that the tail of a Cons is evaluated lazily; the head
definition is straight out of lecture 0 on Scala constructors.
Note that length doesn't go near head, but it's the one that
does the forcing.
All this is part of a general puzzlement about how close Scala streams
are to Haskell lists. I thought Haskell treated head and tail
symmetrically (I'm not a serious Haskell hacker), and Scala forced
head evaluation in more circumstances. I'm trying to figure out
exactly what those circumstances are.
Stream's head is strict and its tail is lazy, as you can see in cons.apply and in the Cons constructor:
def apply[A](hd: A, tl: => Stream[A]) = new Cons(hd, tl)
class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A]
Notice the context in which the take method refers to tail:
cons(head, tail take n-1)
Because the expression tail take n-1 is used as the second argument to cons, which is passed by name, it doesn't force evaluation of tail take n-1, thus doesn't force evaluation of tail.
Whereas in length, the statement
left = left.tail
, by assigning left.tail to a var, does force its evaluation.
Scala is "strict by default". In most situations, everything you reference will be evaluated. We only have lazy evaluation in cases where a method/constructor parameter declares an call-by-name argument with =>, and in the culture we don't typically use this unless there's a special reason.
Let me offer another answer to this, one that just looks from a high level, i.e. without actually considering the code.
If you want to know how long a Stream is, you must evaluate it all the way to the end. Otherwise, you can only guess at its length. Admittedly, you may not actually care about the values (since you only want to count them) but that's immaterial.
On the other hand, when you "take" a certain number of elements from a stream (or indeed any collection) you are simply saying that you want at most that number of elements. The result is still a stream even though it may have been truncated.