The semicolon inference doesn't work when an assignment statement is followed by curly braces in Scala? - 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.

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

Syntax of calling a function in scala

Hi I am studying the scala language and have a question. I am reading a book and one of the example says that 0 to 2 is same as (0).to(2). How can I interpret this syntax?? I mean, I can see that to is a function that takes one integer value as its parameter. But what is "(0)." part?? Thanks
In scala any method taking a single parameter can be written with infix syntax.
So for instance if you have
class Foo(x: Int) {
def add(y: Int) = x + y
}
val a = new Foo(42)
then these two method calls are exactly equivalent
a.add(4) // 46
a add 4 // 46
The reason why there's a parenthesis around the 0 is that in older versions of scala the 0. would have been interpreted as a floating point number, due to the ambiguous value of . (which can be both a decimal separator and a method selector). Since scala 2.11 (or 2.10, I don't remember), this has been fixed, so you can now safely type
0.+(2) // Int: 2
and get an Int back, whereas you would have had a Float in the past, as the compiler would have seen it as
0.0 + (2) // Float: 2
I mean, I can see that to is a function that takes one integer value as its parameter.
No, it's not a function, it's a method.
Methods are invoked by sending a message to an object:
foo.bar(baz)
This means "send the message bar with the object referenced by baz as argument to the object referenced by foo. This will in turn cause the method bar in foo's class or one of its ancestors to be invoked.
So, to is the message, 2 is the argument, and 0 is the receiver of the message.
Scala allows you to use either a . or whitespace for message sending:
foo bar(baz)
// is the same as
foo.bar(baz)
Also, when using whitespace for message sending, you can leave off the parentheses of the last argument list if it has only a single argument:
foo bar baz
// is the same as
foo bar(baz)
And lastly, parentheses are not only used for argument lists, they are also used for grouping. (And tuple literals as well.) You can always surround an expression with parentheses to clarify its precedence:
(foo).bar(baz)
// is the same as
foo.bar(baz)

Scala: Compile time constants

How do you declare compile time constants in Scala? In C# if you declare
const int myConst = 5 * 5;
myConst is in-lined as the literal 25. Is:
final val myConst = 5 * 5
equivalent or is there some other mechanism/ syntax?
Yes, final val is the proper syntax, with Daniel's caveats. However, in proper Scala style your constants should be camelCase with a capital first letter.
Beginning with a capital letter is important if you wish to use your constants in pattern matching. The first letter is how the Scala compiler distinguishes between constant patterns and variable patterns. See Section 15.2 of Programming in Scala.
If a val or singleton object does not begin with an uppercase letter, to use it as a match pattern you must enclose it in backticks(``)
x match {
case Something => // tries to match against a value named Something
case `other` => // tries to match against a value named other
case other => // binds match value to a variable named other
}
final val is the way to do it. The compiler will then make that a compile-time constant if it can.
Read Daniel's comment below for details on what "if it can" means.

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.