What does a pure expression mean in Scala? - scala

I have two questions. The first one: is code a pure expression?
lazy val code: Unit = {
// block of code
var s = "abc"
for (i <- 0 until 10) println(i)
s += s concat "def"
println(s)
}
And the second one: What does a pure expression mean? Is this a some code which does not return anything?

A pure expression is a computation that serves only to produce a resulting value - it has no side effects. In the case of your field code above, you make calls to print stuff to the console (println), which is considered a side effect, so it is not a pure expression. An example of a pure expression would be something like:
lazy val foo = 2 + 3
It does nothing apart from generate the final value for foo, and could safely be replaced by the result of the computation (5) without changing the outcome of the program in any way. If you made such a replacement in your code above:
lazy val code: Unit = ()
you would change the program - it no longer prints anything to the console.
Have a look here, for example, for more information about pure functions and pure expressions, and their significance in functional programming.

Related

what is the usage of getOrElse in scala

I'd like to get values from map like that
user_TopicResponses.put(
"3"+"_"+topicid,
Access.useradVectorMap.getOrElse(
"3"+"_"+topicid,
Access.useradVectorMap.getOrElse("3"+"_"+"0"),
Array(0.0)
)
)
What means if key in map value will be get, of else key is set to "3+"0" and value will also be get.
but it will be reported that:
too many arguments for method getOrElse: (key: String, default: => B1)B
You mixed up parentheses a bit :
Access.useradVectorMap.getOrElse("3"+"_"+"0"),Array(0.0) shoud in fact be
Access.useradVectorMap.getOrElse("3"+"_"+"0",Array(0.0))
It should be ok after that !
First off, I would suggest, at least for debugging purposes, to break your one statement into multiple statements. Your problem stems from a missing/misplaced parentheses. This would be much easier to see if you split your code up.
Secondly, it's good practice to use a variable or function for any repeated code, it makes it far easier to change and maintain (I like to use them for any hard coded value that might change later as well).
In order to only calculate the secondaryValue only if the primaryValue.getOrElse(...) goes to the "else" value, you can use a lazy val, which only evaluates if needed:
val primaryKey = "3_" + topicid
val secondaryKey = "3_0"
val secondaryDefaultValue = Array(0.0)
lazy val secondaryValue = Access.useradVectorMap.getOrElse(secondaryKey, secondaryDefaultValue )
val primaryValue = Access.useradVectorMap.getOrElse(primaryKey, secondaryValue)
user_TopicResponses.put(primaryKey, primaryValue)
This code is far easier to read and, more importantly, far easier to debug

Flatten syntax with yield - improving code readability

I'm trying to improve the readability of my code and I'm having a hard time with this little chunk.
Foo is a method that accepts a List[Ping]
Thing.generate returns a List[Ping]
ListOfPings is a List[Ping]
hasQuality returns a boolean value from evaluating a Ping
Here's the code:
foo((for {
pinger <- listOfPings
} yield pinger.generate.filter(_.hasQuality)).flatten)
Each Ping in listOfPingss is creating a List[Thing] with the generate method, meaning the result of the yield at the end of the loop is a List[List[Ping]].
I'm flattening that List[List[Ping]] (not the individual lists), and putting the whole result into foo
I'm having trouble making this look nicer, potentially with a flatmap? I sincerely appreciate the help.
Something like:
foo {
for (p <- listOfPings ; q <- p.generate if q.hasQuality) yield q
}

Scala lazy val caching

In the following example:
def maybeTwice2(b: Boolean, i: => Int) = {
lazy val j = i
if (b) j+j else 0
}
Why is hi not printed twice when I call it like:
maybeTwice2(true, { println("hi"); 1+41 })
This example is actually from the book "Functional Programming in Scala" and the reason given as why "hi" not getting printed twice is not convincing enough for me. So just thought of asking this here!
So i is a function that gives an integer right? When you call the method you pass b as true and the if statement's first branch is executed.
What happens is that j is set to i and the first time it is later used in a computation it executes the function, printing "hi" and caching the resulting value 1 + 41 = 42. The second time it is used the resulting value is already computed and hence the function returns 84, without needing to compute the function twice because of the lazy val j.
This SO answer explores how a lazy val is internally implemented. In j + j, j is a lazy val, which amounts to a function which executes the code you provide for the definition of the lazy val, returns an integer and caches it for further calls. So it prints hi and returns 1+41 = 42. Then the second j gets evaluated, and calls the same function. Except this time, instead of running your code, it fetches the value (42) from the cache. The two integers are then added (returning 84).

Scala while loop returns Unit all the time

I have the following code, but I can't get it to work. As soon as I place a while loop inside the case, it's returning a unit, no matter what I change within the brackets.
case While(c, body) =>
while (true) {
eval(Num(1))
}
}
How can I make this while loop return a non-Unit type?
I tried adding brackets around my while condition, but still it doesn't do what it's supposed to.
Any pointers?
Update
A little more background information since I didn't really explain what the code should do, which seems to be handy if I want to receive some help;
I have defined a eval(exp : Exp). This will evaluate a function.
Exp is an abstract class. Extended by several classes like Plus, Minus (few more basic operations) and a IfThenElse(cond : Exp, then : Exp, else : Exp). Last but not least, there's the While(cond: Exp, body: Exp).
Example of how it should be used;
eval(Plus(Num(1),Num(4)) would result in NumValue(5). (Evaluation of Num(v : Value) results in NumValue(v). NumValue extends Value, which is another abstract class).
eval(While(Lt(Num(1),Var("n")), Plus(Num(1), Var("n"))))
Lt(a : Exp, b : Exp) returns NumValue(1) if a < b.
It's probably clear from the other answer that Scala while loops always return Unit. What's nice about Scala is that if it doesn't do what you want, you can always extend it.
Here is the definition of a while-like construct that returns the result of the last iteration (it will throw an exception if the loop is never entered):
def whiley[T](cond : =>Boolean)(body : =>T) : T = {
#scala.annotation.tailrec
def loop(previous : T) : T = if(cond) loop(body) else previous
if(cond) loop(body) else throw new Exception("Loop must be entered at least once.")
}
...and you can then use it as a while. (In fact, the #tailrec annotation will make it compile into the exact same thing as a while loop.)
var x = 10
val atExit = whiley(x > 0) {
val squared = x * x
println(x)
x -= 1
squared
}
println("The last time x was printed, its square was : " + atExit)
(Note that I'm not claiming the construct is useful.)
Which iteration would you expect this loop to return? If you want a Seq of the results of all iterations, use a for expression (also called for comprehension). If you want just the last one, create a var outside the loop, set its value on each iteration, and return that var after the loop. (Also look into other looping constructs that are implemented as functions on different types of collections, like foldLeft and foldRight, which have their own interesting behaviors as far as return value goes.) The Scala while loop returns Unit because there's no sensible one size fits all answer to this question.
(By the way, there's no way for the compiler to know this, but the loop you wrote will never return. If the compiler could theoretically be smart enough to figure out that while(true) never terminates, then the expected return type would be Nothing.)
The only purpose of a while loop is to execute a side-effect. Or put another way, it will always evaluate to Unit.
If you want something meaningful back, why don't you consider using an if-else-expression or a for-expression?
As everyone else and their mothers said, while loops do not return values in Scala. What no one seems to have mentioned is that there's a reason for that: performance.
Returning a value has an impact on performance, so the compiler would have to be smart about when you do need that return value, and when you don't. There are cases where that can be trivially done, but there are complex cases as well. The compiler would have to be smarter, which means it would be slower and more complex. The cost was deemed not worth the benefit.
Now, there are two looping constructs in Scala (all the others are based on these two): while loops and recursion. Scala can optimize tail recursion, and the result is often faster than while loops. Or, otherwise, you can use while loops and get the result back through side effects.

Why does Scala's semicolon inference fail here?

On compiling the following code with Scala 2.7.3,
package spoj
object Prime1 {
def main(args: Array[String]) {
def isPrime(n: Int) = (n != 1) && (2 to n/2 forall (n % _ != 0))
val read = new java.util.Scanner(System.in)
var nTests = read nextInt // [*]
while(nTests > 0) {
val (start, end) = (read nextInt, read nextInt)
start to end filter(isPrime(_)) foreach println
println
nTests -= 1
}
}
}
I get the following compile time error :
PRIME1.scala:8: error: illegal start of simple expression
while(nTests > 0) {
^
PRIME1.scala:14: error: block must end in result expression, not in definition
}
^
two errors found
When I add a semicolon at the end of the line commented as [*], the program compiles fine. Can anyone please explain why does Scala's semicolon inference fail to work on that particular line?
Is it because scala is assuming that you are using the syntax a foo b (equivalent to a.foo(b)) in your call to readInt. That is, it assumes that the while loop is the argument to readInt (recall that every expression has a type) and hence the last statement is a declaration:
var ntests = read nextInt x
wherex is your while block.
I must say that, as a point of preference, I've now returned to using the usual a.foo(b) syntax over a foo b unless specifically working with a DSL which was designed with that use in mind (like actors' a ! b). It makes things much clearer in general and you don't get bitten by weird stuff like this!
Additional comment to the answer by oxbow_lakes...
var ntests = read nextInt()
Should fix things for you as an alternative to the semicolon
To add a little more about the semicolon inference, Scala actually does this in two stages. First it infers a special token called nl by the language spec. The parser allows nl to be used as a statement separator, as well as semicolons. However, nl is also permitted in a few other places by the grammar. In particular, a single nl is allowed after infix operators when the first token on the next line can start an expression -- and while can start an expression, which is why it interprets it that way. Unfortunately, although while can start a expression, a while statement cannot be used in an infix expression, hence the error. Personally, it seems a rather quirky way for the parser to work, but there's quite plausibly a sane rationale behind it for all I know!
As yet another option to the others suggested, putting a blank newline between your [*] line and the while line will also fix the problem, because only a single nl is permitted after infix operators, so multiple nls forces a different interpretation by the parser.