Why does Scala's semicolon inference fail here? - scala

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.

Related

scala nested for/yield generator to extract substring

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)

scala semicolon inference example

The "Programming in scala" introduces the rules of semicolon inference:
In short, a line ending is treated as a semicolon unless one of the following conditions is true:
The line in question ends in a word that would not be legal as the end of a statement, such as a period or an infix operator.
The next line begins with a word that cannot start a statement.
The line ends while inside parentheses(...) or brackets[...], because these cannot contain multiple statements anyway.
But I can't find an example that in the second condition,who can give an example?
I have tried the following code because * cannot start a statement,but it failed!
1 * 2
*3
The "Programming in scala" introduces the rules of semicolon inference:
In short, a line ending is treated as a semicolon unless one of the following conditions is true:
The line in question ends in a word that would not be legal as the end of a statement, such as a period or an infix operator.
The next line begins with a word that cannot start a statement.
The line ends while inside parentheses(...) or brackets[...], because these cannot contain multiple statements anyway.
Note that this is a rather simplified view. The full rules are in section 1.2 Newline Characters of the Scala Language Specification.
But I can't find an example that in the second condition,who can give an example?
According to the SLS:
The tokens that can begin a statement are all Scala tokens except the following delimiters and reserved words:
catch
else
extends
finally
forSome
match
with
yield
,
.
;
:
=
=>
<-
<:
<%
>:
#
[
)
]
}
So, one example could be:
return 42
.toString()
This is equivalent to
return 42.toString(); // returns the `String` "42"
and not
return 42; // returns the `Int` 42
.toString() // dead code
I have tried the following code because * cannot start a statement,but it failed!
1 * 2
*3
What makes you think that * cannot start a statement? Please, re-read the spec carefully. A method call is perfectly legal starting a statement:
foo(bar)
is valid, and so is
*(3)
Ergo, * can start a statement. Full example:
object Test
def test = {
1 * 2
*(3)
}
def *(x: Int) = {
println(x)
x + 1
}
}
Test.test
// 3
//=> res0: Int = 4

What does a pure expression mean in 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.

How to avoid return statement and escape from for loop?

I've been told to avoid use of return in Scala, although I'm not sure why.
I've got the following code, and it doesn't seem to return the proper thing unless I put the return keyword in there. Why do I need to put return?
def nextParen(chars: List[Char]): List[Char] =
for(i <- 0 to chars.size - 1) {
if(chars(i) == '(' || chars(i) == ')') {
return chars.slice(i, chars.size) // return HERE!
}
}
List.empty
}
The argument for avoiding return is that it leads to code that is less readable, and not refactor-safe. It's not an absolute rule, if you find an algorithm that's best expressed that way, but usually code can be made clearer by writing it as an expression.
This particular code looks to be equivalent to:
def nextParen(chars: List[Char]) =
chars.dropWhile{c => c != '(' && c != ')'}
In general, try to focus on writing expressions rather than procedures; rather than telling the compiler what steps it should take, tell it what the value is. Even if you didn't know about dropWhile, you could write the loop as a fold (e.g. foldLeft) that says what to do at each element of the list, and then the case where the list is empty at the end would fall out naturally, rather than needing two different branches for where there is a match and where there isn't.
There's nothing wrong with using return when it clearly expresses your intent in a good algorithm. However, you should be cautious about using it because it isn't necessary, and most things you want to do already have decent implementations in the collections library.
So, for example, your code works but is O(n^2) in the size of the list because you're indexing into a linear data structure. It's much better to use
chars.dropWhile(c => c != '(' && c != ')')
or if you don't know about that, any of a huge number of alternatives:
val i = chars.indexWhere(c => c == '(' || c == ')')
if (i < 0) chars take 0 else chars drop i
var found = false
chars.filter(c => found || { found = (c == '(' || c == ')'); found })
You can probably come up with half a dozen more without trying too hard. (Fold with an indicator, for/yield with an if clause, span, etc.)
So the best reason to not use return is that you should know your library. Usually you don't need it; it's better to use a stock method that computes what you want.
You are using a for in the imperative sense above. You don't have to use a return if you use it in a more functional sense i.e., as a for-yield or fold or takeWhile.
I think one of the biggest thing to wrap your head around when you move from imperative to functional (side-effect free) is the notion that you can express your code a sequence of expressions, each of which evaluates to a value. For example, a for-yield expression evaluates to a value. So in an imperative world you are executing a sequence of statements that is changing the state (data structures, console etc) around you.
PS: I've used a lot of terms (e.g., side-effect, for-yield, value) that may sound unfamiliar to a new Scala programmer. But with more experience they will make more sense. I would highly recommend this book - Structure and Interpretation of Computer Programs

The semicolon inference doesn't work when an assignment statement is followed by curly braces in Scala?

At http://www.artima.com/pins1ed/builtin-control-structures.html#7.7,
I see the following code
val a = 1;
{
val a = 2
println(a)
}
println(a)
where it says that the semicolon is required here, but why?
From the rule at http://www.artima.com/pins1ed/classes-and-objects.html#4.2 ,
I think the semicolon should be auto added since
val a = 1 can be a legal statement.
The next line begins with {, which I think can start a legal statement. (Since there's no compile error if I add the semicolon and separate the first two lines into two statements.)
val a = 1 is not in parentheses or brackets.
Because it would be a legal call to apply:
implicit class RichInt(i: Int) {
def apply(thunk: => Unit) = 33
}
val a = 1
{
val a = 2
println(a)
}
println(a) // 33 !
1 { ... } is short for 1.apply {...}. Now apply is not defined for an Int by default, but as the implicit enrichment shows, it is perfectly possible.
Edit: The semicolon inference conditions are described in 'ยง1.2 Newline Characters' of the Scala Language Specification. The inferred semicolon is called 'special token "nl"' in that text.
In general, three rules are given (summarised ex-negativo in this blog entry), and in your example they are all satisfied. The reason that the semicolon is still not inferred is given further down in the text.
The Scala grammar ... contains productions where optional nl tokens, but not semicolons, are accepted. This has the effect that a newline in one of these positions does not [!] terminate an expression or statement.
The relevant case of such an extra rule is the following:
A single new line token is accepted
โ€“ in front of an opening brace โ€œ{โ€, if that brace is a legal continuation of the current statement or expression ...
Example 1.2.2 shows the case of anonymous an subclass which I had referred to in the comment.