val behavior in scala REPL and Intellij - scala

as expected reassignment is giving error like below in REPL
scala> val a=1
a: Int = 1
scala> a=2
<console>:12: error: reassignment to val
a=2
^
But the below reassignment is not giving error in REPL when a=2 preceded with val.
scala> val a=1
a: Int = 1
scala> val a=2
a: Int = 2
When I execute the below code in Intellij its giving error.
object Test {
def main(args: Array[String]) {
val x = 1
val x = 2
}
}
Why val a=1 and val a=2 are not giving any error in REPL(error if it is only a=2) but error in Intellij.

From Scala docs REPL overview:
every line of input is compiled separately.
dependencies on previous lines are included by automatically generated imports.
Combining these two facts, we can understand that they are not in the same namespace, unlike the example you provided which 2 variables called x are in the same class.

The REPL is intended for rapid friction-less experimentation. It would be very annoying if you had to restart from scratch just because you accidentally mistyped val a = 32 when you meant val a = 23.
Therefore, the REPL is designed in such a way that it gives the appearance of breaking the rules of Scala, although it actually doesn't. The code that gets actually compiled corresponding to the code you entered looks a little bit like this:
object line$1 {
val a=1
}
object line$2 {
import line$1._
val a=2
}

Related

Why Scala in REPL (or worksheet) and Scala in IDE don't work the same? [duplicate]

as expected reassignment is giving error like below in REPL
scala> val a=1
a: Int = 1
scala> a=2
<console>:12: error: reassignment to val
a=2
^
But the below reassignment is not giving error in REPL when a=2 preceded with val.
scala> val a=1
a: Int = 1
scala> val a=2
a: Int = 2
When I execute the below code in Intellij its giving error.
object Test {
def main(args: Array[String]) {
val x = 1
val x = 2
}
}
Why val a=1 and val a=2 are not giving any error in REPL(error if it is only a=2) but error in Intellij.
From Scala docs REPL overview:
every line of input is compiled separately.
dependencies on previous lines are included by automatically generated imports.
Combining these two facts, we can understand that they are not in the same namespace, unlike the example you provided which 2 variables called x are in the same class.
The REPL is intended for rapid friction-less experimentation. It would be very annoying if you had to restart from scratch just because you accidentally mistyped val a = 32 when you meant val a = 23.
Therefore, the REPL is designed in such a way that it gives the appearance of breaking the rules of Scala, although it actually doesn't. The code that gets actually compiled corresponding to the code you entered looks a little bit like this:
object line$1 {
val a=1
}
object line$2 {
import line$1._
val a=2
}

Get objects out of scala interpreter

I spent hours investigating one topic. I am definitely out of my depth here. What I want is to run the scala interpreter programmatically and be able to extract object values from the interpreter. for example, if I send
val a = 1
val b = a + 1
I want to be able to read out b as an Int, not just a string printed out like
b = 2
The source code is dense. So far I don't see any part which would allow such an extraction. Any experts here who can give me a tip or tell me this is utter nonsense?
How do I get typed objects out of the scala interpreter between sessions?
Use JSR 223.
Welcome to Scala version 2.11.7 [...]
scala> import javax.script._
import javax.script._
scala> val engine = (new ScriptEngineManager).getEngineByName("scala")
engine: javax.script.ScriptEngine = scala.tools.nsc.interpreter.IMain#4233e892
scala> engine.eval("val a = 1")
res0: Object = 1
scala> engine.eval("val b = a + 1")
res1: Object = 2
scala> engine.eval("b").asInstanceOf[Int]
res2: Int = 2

The differences between using `val` and `def` for function definition in Scala REPL?

I defined two functions(method) in Scala REPL:
scala> val b=(x:Int)=>x+1
b: Int => Int = <function1>
scala> def c(x:Int)=x+1
c: (x: Int)Int
And the usage:
scala> b(1)
res4: Int = 2
scala> c(1)
res5: Int = 2
While both definition works, it seems that b and c have different type. And I was wondering whether there are some differences between them. Why doesn't Scala use the same type for b and c? Does anyone have ideas about this?
Not duplicate:
This question is not a duplicate of the linked question. Even though
it asks about the difference between using def and val to define a
function, the code example makes it clear that the asker is confused
about the difference between methods and functions in Scala. The
example doesn't use a def to define a function at all. – Aaron
Novstrup 7 hours ago
The use of def creates a method (in the case of the REPL it will create a method in some global invisible object), val instead will create an anonymous function and assign it to the symbol you specified.
When invoking those they are pretty much the same thing; when you pass them around there is a difference but Scala hides it from you by performing the ETA expansion transparently. As an example if you define this:
def isEven(i: Int): Boolean = i % 2 == 0
And then call
list.filter(isEven)
Scala is transforming that for you in a way that is similar to using the val way instead; take it as a pseudo-code as I don't know so well the scala internals but at at high level this is what happens:
list.filter((i: Int) => isEven(i))

Why can't i define a variable recursively in a code block?

Why can't i define a variable recursively in a code block?
scala> {
| val test: Stream[Int] = 1 #:: test
| }
<console>:9: error: forward reference extends over definition of value test
val test: Stream[Int] = 1 #:: test
^
scala> val test: Stream[Int] = 1 #:: test
test: Stream[Int] = Stream(1, ?)
lazy keyword solves this problem, but i can't understand why it works without a code block but throws a compilation error in a code block.
Note that in the REPL
scala> val something = "a value"
is evaluated more or less as follows:
object REPL$1 {
val something = "a value"
}
import REPL$1._
So, any val(or def, etc) is a member of an internal REPL helper object.
Now the point is that classes (and objects) allow forward references on their members:
object ForwardTest {
def x = y // val x would also compile but with a more confusing result
val y = 2
}
ForwardTest.x == 2
This is not true for vals inside a block. In a block everything must be defined in linear order. Thus vals are no members anymore but plain variables (or values, resp.). The following does not compile either:
def plainMethod = { // could as well be a simple block
def x = y
val y = 2
x
}
<console>: error: forward reference extends over definition of value y
def x = y
^
It is not recursion which makes the difference. The difference is that classes and objects allow forward references, whereas blocks do not.
I'll add that when you write:
object O {
val x = y
val y = 0
}
You are actually writing this:
object O {
val x = this.y
val y = 0
}
That little this is what is missing when you declare this stuff inside a definition.
The reason for this behavior depends on different val initialization times. If you type val x = 5 directly to the REPL, x becomes a member of an object, which values can be initialized with a default value (null, 0, 0.0, false). In contrast, values in a block can not initialized by default values.
This tends to different behavior:
scala> class X { val x = y+1; val y = 10 }
defined class X
scala> (new X).x
res17: Int = 1
scala> { val x = y+1; val y = 10; x } // compiles only with 2.9.0
res20: Int = 11
In Scala 2.10 the last example does not compile anymore. In 2.9.0 the values are reordered by the compiler to get it to compile. There is a bug report which describes the different initialization times.
I'd like to add that a Scala Worksheet in the Eclipse-based Scala-IDE (v4.0.0) does not behave like the REPL as one might expect (e.g. https://github.com/scala-ide/scala-worksheet/wiki/Getting-Started says "Worksheets are like a REPL session on steroids") in this respect, but rather like the definition of one long method: That is, forward referencing val definitions (including recursive val definitions) in a worksheet must be made members of some object or class.

issue `object Foo { val 1 = 2 }` in scala

I found this issue of scala: https://issues.scala-lang.org/browse/SI-4939
Seems we can define a method whose name is a number:
scala> object Foo { val 1 = 2 }
defined module Foo
But we can't invoke it:
scala> Foo.1
<console>:1: error: ';' expected but double literal found.
Foo.1
And we can invoke it inside the object:
scala> object O { val 1 = 1; def x = 1 }
defined module O
scala> O.x
res1: Int = 1
And follow will throw error:
scala> object O { val 1 = 2; def x = 1 }
defined module O
scala> O.x
scala.MatchError: 2
at O$.<init>(<console>:5)
at O$.<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
I use scalac -Xprint:typer to see the code, the val 1 = 2 part is:
<synthetic> private[this] val x$1: Unit = (2: Int(2) #unchecked) match {
case 1 => ()
}
From it, we can see the method name changed to x$1, and only can be invoked inside that object.
And the resolution of that issue is: Won't Fix
I want to know is there any reason to allow a number to be the name of a method? Is there any case we need to use a "number" method?
There is no name "1" being bound here. val 1 = 2 is a pattern-matching expression, in much the same way val (x,2) = (1,2) binds x to 1 (and would throw a MatchError if the second element were not thet same). It's allowed because there's no real reason to add a special case to forbid it; this way val pattern matching works (almost) exactly the same way as match pattern-matching.
There are usually two factors in this kind of decision:
There are many bugs in Scalac that are much higher priority, and bug fixing resources are limited. This behavior is benign and therefore low priority.
There's a long term cost to any increases in the complexity of the language specification, and the current behavior is consistent with the spec. Once things start getting special cased, there can be an avalanche effect.
It's some combination of these two.
Update. Here's what seems strange to me:
val pair = (1, 2)
object Foo
object Bar
val (1, 2) = pair // Pattern matching on constants 1 and 2
val (Foo, Bar) = pair // Pattern matching on stable ids Foo and Bar
val (foo, bar) = pair // Binds foo and bar because they are lowercase
val 1 = 1 // Pattern matching on constant 1
val Foo = 1 // *Not* pattern matching; binds Foo
If val 1 = 1 is pattern matching, then why should val Foo = 1 bind Foo rather than pattern match?
Update 2. Daniel Sobral pointed out that this is a special exception, and Martin Odersky recently wrote the same.
Here's a few examples to show how the LHS of an assignment is more than just a name:
val pair = (1, 2)
val (a1, b1) = pair // LHS of the = is a pattern
val (1, b2) = pair // okay, b2 is bound the the value 2
val (0, b3) = pair // MatchError, as 0 != 1
val a4 = 1 // okay, a4 is bound to the value 1
val 1 = 1 // okay, but useless, no names are bound
val a # 1 = 1 // well, we can bind a name to a pattern with #
val 1 = 0 // MatchError
As always, you can use backticks to escape the name. I see no problem in supporting such names – either you use them and they work for you or they do not work for you, and you don’t use them.