Scala REPL issue - Multiexpression issue - scala

I am new to scala and getting below exception while using :paste command in REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
1+2
println("welcome to scala world")
// Exiting paste mode, now interpreting.
<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses
1+2
^
welcome to scala world
scala>
scala version : Scala code runner version 2.12.3 -- Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc

It's not an exception, just a warning that you can ignore. It warns that in paste mode the expression 1+2 has no effect and the result won't be printed.
If you would enter both of your lines in normal mode the REPL will print the result of each expression.
scala> 1+2
res1: Int = 3
scala> println("welcome to scala world")
welcome to scala world
The second part of the warning is for the case that you intend a multi-line expression where each line is a valid expression, e.g.
scala> :paste
// Entering paste mode (ctrl-D to finish)
1+2
-5
// Exiting paste mode, now interpreting.
<console>:48: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
1+2
^
res1: Int = -5
which is different from
scala> :paste
// Entering paste mode (ctrl-D to finish)
(1+2
-5)
// Exiting paste mode, now interpreting.
res22: Int = -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
}

Using vim editor to create a Scala script within REPL

Version of Scala I am using is Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121) and the Jline Library present is 2.14.3 .
This could sound silly but I am trying to figure out the problem when trying to create a scala file using editor cmd line vi or vim during the Scala REPL mode its throwing error. Below is my error .. Could you please let me know if there is any specific Scala Terminal console that I am suppose to use or am I doing something wrong ?
scala> vi test1.scala
<console>:1: error: ';' expected but '.' found.
vi test1.scala
I am able to do a VI and VIM as well in my system without the SCALA REPL mode but when I am in REPL I am not able to create a scala script file and execute it . What could be wrong ? Is there any settings that needs to be enabled for this ?
For saving your REPL history, use :save file.
There is limited support for using an external editor. The result of the edit is run immediately. After a reset, only the edited lines are in session history, so save will save only those lines.
$ EDITOR=gedit scala
Welcome to Scala 2.12.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> val x = 42
x: Int = 42
scala> println(x)
42
scala> :edit -2
+val x = 17
+println(x)
17
x: Int = 17
scala> :hi 3
1896 val x = 17
1897 println(x)
1898 :hi 3
scala> :reset
Resetting interpreter state.
Forgetting this session history:
val x = 42
println(x)
val x = 17
println(x)
Forgetting all expression results and named terms: $intp, x
scala> :ed 1896+2
+val x = 5
+println(x)
5
x: Int = 5
scala> :save sc.sc
scala> :load sc.sc
Loading sc.sc...
x: Int = 5
5

spark-shell cannot parse Scala lines that start with dot / period

Whenever I find some Scala / Spark code online, I want to directly paste it into spark-shell to try it out. (I am using spark-shell with Spark 1.6 on both CentOS and Mac OS.)
Generally, this approach works well, but I always have problems when lines start with a dot / period (indicating a continuing method call). If I move the dot to the previous line, it works.
Example: Here is some code I found online:
val paramMap = ParamMap(lr.maxIter -> 20)
.put(lr.maxIter, 30)
.put(lr.regParam -> 0.1, lr.threshold -> 0.55)
So when I paste this directly into spark-shell, I see this error:
scala> val paramMap = ParamMap(lr.maxIter -> 20)
paramMap: org.apache.spark.ml.param.ParamMap =
{
logreg_d63b85553548-maxIter: 20
}
scala> .put(lr.maxIter, 30)
<console>:1: error: illegal start of definition
.put(lr.maxIter, 30)
^
scala> .put(lr.regParam -> 0.1, lr.threshold -> 0.55)
<console>:1: error: illegal start of definition
.put(lr.regParam -> 0.1, lr.threshold -> 0.55)
^
However, when I instead move the dot to the previous line, everything is ok.
scala> val paramMap = ParamMap(lr.maxIter -> 20).
| put(lr.maxIter, 30).
| put(lr.regParam -> 0.1, lr.threshold -> 0.55)
paramMap: org.apache.spark.ml.param.ParamMap =
{
logreg_d63b85553548-maxIter: 30,
logreg_d63b85553548-regParam: 0.1,
logreg_d63b85553548-threshold: 0.55
}
Is there a way to configure spark-shell so that it will accept lines that start with a dot (or equivalently, so that it will continue lines even if they don't end in a dot)?
There must be no leading whitespace.
scala> "3"
res0: String = 3
scala> .toInt
res1: Int = 3
scala> "3"
res2: String = 3
scala> .toInt
<console>:1: error: illegal start of definition
.toInt
^
PS: Maybe it should ignore whitespace when a dot is detected. A JIRA was added on that concern here.
Use :paste command:
scala> :paste
// Entering paste mode (ctrl-D to finish)
if (true)
print("that was true")
else
print("false")
// Exiting paste mode, now interpreting.
that was true
you can also wrap your expression with curly braces
val paramMap = { ParamMap(lr.maxIter -> 20)
.put(lr.maxIter, 30)
.put(lr.regParam -> 0.1, lr.threshold -> 0.55)
}
This is because: The REPL is “greedy” and consumes the first full statement you type in, so attempting to paste blocks of code into it can fail
for more details see: http://alvinalexander.com/scala/scala-repl-how-to-paste-load-blocks-of-source-code
There is also nice feature :paste -raw
See http://docs.scala-lang.org/overviews/repl/overview.html
The Spark shell has a built-in mechanism to allow for pasting in multiple line Spark Scala code or writing line-by-line Spark Scala code: by wrapping your code in parenthesis (). Moving your dots to the end of the line is not needed.
In your example start off with val paramMap = (. From here you can write each line by hand or paste in your multi-line linear regression hyperparameter code. Then add one more parenthesis ) after your code is finished to encapsulate it. When using this method don't use tab for indentation but use two spaces instead.
Full code example:
scala> val paramMap = (ParamMap(lr.maxIter -> 20)
| .put(lr.maxIter, 30)
| .put(lr.regParam -> 0.1, lr.threshold -> 0.55)
| )
You can also put the periods on the line before, then it works fine. Although this may break style conventions
val paramMap = ParamMap(lr.maxIter -> 20).
put(lr.maxIter, 30).
put(lr.regParam -> 0.1, lr.threshold -> 0.55)

How do chain commands in Scala interpreter?

In windows batch, you chain commands with && operator. How do you do the same in scala interpreter? It looks stupid that I need :load file and call import mainobj._ after every load. Obviously, you want to chain them into one liner.
You could write multiple statements in one line of Scala with ;
scala> val a:Int = 3; val b:Int = 4; println(a+b);
7
a: Int = 3
b: Int = 4
Or first type { then write your commands line by line finishing with }
scala> {
| val x:Int = 1
| val y:Int = 2
| println(x + y)
| }
3
Or you can use :paste to turn on paste mode, and then enter your code.
scala> :paste
// Entering paste mode (ctrl-D to finish)
if (true)
print("that was true")
else
print("false")
// Exiting paste mode, now interpreting.
that was true

Evaluate string command in Scala from REPL

Is there a way to evaluate a arbitrary string from Scala as if the same text was entered into the Scala REPL directly? I mean, I would like to do something like this:
scala> eval("val x = 42")
scala> x
res2: Int = 42
Since the Scala REPL is accepting commands in an eval loop using jline (I believe) and then compiling/interpreting it, there has to be a way to submit an arbitrary line of text. I am willing to hack the Scala REPL if necessary.
No REPL hacking necessary—just switch to power user mode, which gives you access to the current scala.tools.nsc.interpreter.IMain as intp:
scala> :power
** Power User mode enabled - BEEP BOOP SPIZ **
** :phase has been set to 'typer'. **
** scala.tools.nsc._ has been imported **
** global._ and definitions._ also imported **
** Try :help, vals.<tab>, power.<tab> **
scala> intp.interpret("val x = 42")
x: Int = 42
res0: scala.tools.nsc.interpreter.package.IR.Result = Success
scala> x
res1: Int = 42
This works since at least 2.9.1.
Another opportunity is to use Eval from Twitter Utility:
val x: Int = new Eval()("1 + 1")