I have the following code in Scala:
var i: Int = 0
var sum: Int = 0
for(i<- 1 to 10)
{
sum= sum+1
}
println(sum)
Although it is elementary I noticed that if you write
sum=-sum+1
it produces an error.
Also if you write
sum=-(sum+1)
it produces an error too and
sum= -(sum+1)
produces zero. Why zero?
This doesn't happen in C++ for instance and I found it odd. What is happening and why? Does it matter if you use spaces in Scala?
In the first two cases, the Scala compiler is likely interpreting =- as an operator, instead of associating the - with the right-hand side of the assignment. The third case was answered in the comments.
Related
I am new to scala. Pls be gentle. My problem for the moment is the syntax error.
(But my ultimate goal is to print each group of 3 characters from every string in the list...now i am merely printing the first 3 characters of every string)
def do_stuff():Unit = {
val s = List[String]("abc", "fds", "654444654")
for {
i <- s.indices
r <- 0 to s(i).length by 3
println(s(i).substring(0,3))
} yield {s(i)}
}
do_stuff()
i am getting this error. it is syntax related, but i dont undersatnd..
Error:(12, 18) ')' expected but '.' found.
println(s(i).substring(0,3))
That code doesn't compile because in a for-comprehension, you can't just put a print statement, you always need an assignment, in this case, a dummy one can solve your porblem.
_ = println(s(i).substring(0,3))
EDIT
If you want the combination of 3 elements in every String you can use combinations method from collections.
List("abc", "fds", "654444654").flatMap(_.combinations(3).toList)
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.
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).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Return in Scala
I have just started using Scala and have come across some behavior that I don't really understand, and I'm hoping the stackoverflow community can shed some light.
Using this test:
example(1,List(1))
This code works as I would expect - 0 is returned on the second iteration:
def example(value: Int, list: List[Int]): Int = {
if (list.isEmpty)
return 0
else
return 1
example(value - list.head, list.tail) + example(value, list.tail);
}
However, this code does not - it throws a NoSuchElementException("head of empty list") on the second iteration:
def example(value: Int, list: List[Int]): Int = {
if (list.isEmpty)
0
else
1
example(value - list.head, list.tail) + example(value, list.tail);
}
The difference appears to be that in the second example, Scala is assuming "0" and "1" are not return values but expressions to be evaluated because there is another expression at the end of the function. It makes sense that the first example would return as expected due to the explicit "return" keyword.
However, given the syntax of the if statement in second example, I would think the compiler would realize that "0" is not an expression to be evaluated, but rather a return value. Why is this not the case?
You should read the answer here for information about implicit returning since that part of your question is an exact duplicate.
But I'll answer specifically your point about "I would think the compiler would realize that "0" is not an expression to be evaluated, but rather a return value", since it's an interesting observation.
The simple answer is that 0 is an expression... it just happens to be the case that its evaluation is pretty simple. Scala doesn't make a distinction between "expressions that require effort" and "expressions that are easy" when it decides how to process your code. It just processes it the way it's told.
More importantly, if the Scala compiler did get into the business of guessing your intent, that would get pretty crazy, and would make coding a lot more challenging!
To see why we do not want this, let's look at your code that you posted:
def example(value: Int, list: List[Int]): Int = {
if (list.isEmpty)
0
else
1
example(value - list.head, list.tail) + example(value, list.tail);
}
As you mentioned, the 0 and 1 bits aren't really doing anything. So maybe this hypothetical compiler would say "Hey! The only interesting thing I can do with these is to return them!" and thus makes them return. We'll now we've got an if/else in which both sides return. In other words, if list is empty, we return, and if it's not empty, we return. So we always return, and the function ends.
But wait!! There's another line after the if/else expression! So our hypothetical compiler says "Hey! If I return here, then I won't ever execute that line! And that line looks pretty important. Maybe I shouldn't return, so that I can execute it." But then it realizes "Oh no! If i don't return the 0 or 1, then they are pointless! I have to return them!". "But that last line is still there!". "Ahhhhhhh!!!!1!!".
So maybe it's better that the compiler doesn't try to guess what we want and instead just does what we tell it.
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.