My question is quick I'm working on a small console for reading input in and then calling the appropriate code. I'm using sbt and I've encountered an issue where when I try to read input after running my program with sbt run, inside sbt console, or even in the plain old scala interpreter.
The prompt appears to just hang, but if I hit return it does actually read the input in. Though the shell's buffer remains empty. Here is the general code I've been trying that has been giving me the issue.
import java.io._
val s = new BufferedReader(new InputStreamReader(System.in))
val line = s.readLine
println(line)
Does anyone know why this is, and if so is there a way to fix this? I would love to be able to see what I type when I run my program from sbt. Without seeing my typing in the shell it makes the testing and development of my project much less enjoyable.
This is really a Java API question, although in Scala. BufferedReader.readLine() will consume all the characters you type from System.in until it has a whole line, at which time it will return the line as you said.
Console input was difficult in Java with the original java.io classes. Prior to Java6, I've seen a couple of messy solutions to this, but fortunately a new class was introduced with that release to make it much easier: java.io.Console. I think it then becomes as simple as
val line = System.console.readLine
println(line)
Related
I know sbt console will open an interactive Scala REPL and load in all the library dependencies so people can test Scala code right there. However, I wonder if there's anyway to use and treat in a way so that people can interact with my programs directly, instead of interacting with libraries.
For example, if I write a Vector class, how can someone call it from sbt console or any other Scala REPL interface??
Think of it as that you are trying to write a Scala library but you want to provide a simple REPL interface for people to interact with it, like R, instead of asking people to add the library as dependency.
The effect is similar as described here: http://stanford-ppl.github.io/Delite/optiml/getting_started.html
Maybe this will help.
You can use initialCommands key in sbt to do this
So in build.sbt if you put
initialCommands in console := """import my.project._
val myObj = MyObject("Hello", "World")
"""
after you type 'console', you can start using myObj or the classes in my.project
http://www.scala-sbt.org/0.13.5/docs/Howto/scala.html#initial
Yes you can, but you cannot use modified code without reloading the REPL. Just run:
sbt "~ ; console"
And then import your classes with import your.package._ and use them from there.
If you make any changes to your library code, just hit CTRL+D or :quit and it will detect file changes, compile them and enter the REPL again. You can then use the history (navigating with the arrows up/down) to execute anything from the previous session again.
Compiling Spark gives this compile error :
To fix I modify Utils.classIsLoadable method to just return true:
def classIsLoadable(clazz: String): Boolean = {
// Try { Class.forName(clazz, false, getContextOrSparkClassLoader) }.isSuccess
true
}
I realise this is not a good fix, but so far Spark seems to be running correctly from source. Has this compile error been experienced before and is there a fix? Will returning true suffice for now , I'm not sure what impact modifying this return value may have?
I suggest compiling Spark from the command-line using Maven or SBT instead of trying to use your IDE's compiler. Many of the core Spark developers use IntelliJ for editing Spark's source code but still use the command-line compilers, largely because it's been difficult to get the project to build correctly inside IDEs. Even if you're using an external compiler, you should still be able to benefit from IntelliJ's syntax highlighting, type checking, etc.
Here's a relevant discussion from the Spark developer mailing list: http://apache-spark-developers-list.1001551.n3.nabble.com/IntelliJ-IDEA-cannot-compile-TreeNode-scala-td7090.html
Note that Spark users should be able to use IntelliJ to compile applications that depend on Spark; this issue only affects developers who want to build Spark itself.
If you're interested in fixing the build to work with IntelliJ, I recommend opening a ticket on the Spark issue tracker.
Why is it faster to call external scala compiler than use the runtime interpreter library?
In the code below it takes almost 2s to warm up the interpreter.
val out = new PrintStream(new FileOutputStream("/dev/null"))
val flusher = new java.io.PrintWriter(out)
val interpret = {
val settings = new scala.tools.nsc.GenericRunnerSettings(println _)
settings.usejavacp.value = true
new scala.tools.nsc.interpreter.IMain(settings, flusher)
}
interpret.interpret(" ") // <-- warming up
interpret.interpret(" Hello World ")
In the other hand, when running Scala compiler from command line like in a shell session:
scala HelloWorld.scala
it takes less than 0.5s to print a Hello World.
I am trying to parse+execute some Java, Scala or similar code given in a string during runtime (it is a script interpreter, i.e. it will be run only one time during my app execution).
Scala code would be better obviously, but only if it can be as fast as the Java option.
Is there any faster alternative than nsc.interpreter and external compiler to execute code from a string at runtime?
The best I could found was Janino; it is faster than Scala compiler and does not require the JDK (a very interesting feature).
As a last resource, how fast are Java Scripting Engines compared to a reflected or bytecode-compiled Java code? I found that, at least, they can be compiled: Compiling oft-used scripts.
Chosen solution:
runtimecompilescala.
There are many things left unstated (like memory settings), but you're comparing apples and oranges.
The command-line script runner is not a REPL session; instead, it wraps your code in a simple object with a main method, compiles and runs that.
By contrast, each interpreted line (or compilable thing) in the REPL is wrapped in an object (with the session history imported so you can refer to past results).
Even modulo REPL start-up, this has performance consequences, see this issue.
The simple wrap-it logic for the script runner is built into the parser. Here is how the script runner runs the compilation. Or, it looks like this is how -e is handled.
Edit: your comment to your question implies that you really want fsc compile server behavior. Fire up fsc and use the compile client.
How do I determine if a Scala module is opened as script or if it is regularly imported?
This question is about the same issue as previous Python question:
how do I determine whether a python script is imported as module or run as script?
but for Scala
If you just need a quick hack for personal use, you can launch the Scala interpreter with a shell script that also sets an environment variable indicating that the interpreter is running.
Also, keep in mind that there's a difference between Scala and Python that makes the question somewhat moot: In Scala, code expressions can't appear at the top level, unless it's a Scala script. So you'll never really have the ambiguity of writing a Scala script and then wondering if it's being executed some other way.
All Scala modules are imported regularly, because there is no such thing as opening as a script.
Scala doesn't have the equivalent of Python's __main__ as far as I know so it can't be done in the same way. But I argue you shouldn't be doing this anyway - just write tests for your module or write a script that imports the module.
A dirty hack could be to throw and exception and get the trace. You can then examine it to try to guess the context. For example a method like:
def stackTrace: Array[StackTraceElement] =
try {
1/0 // cause exception
Array() //Never executed
} catch {
case e: Exception => e.getStackTrace
}
Will return the full stack trace as an array of StackTraceElement.
However, writing the trace analysis code will be tedious and I don't see any situation where it may be worth of it...
I'm using Scala Source.fromFile however I can't seem to find a nice way of getting it to close the underlying InputStream once the file has been read.
Here's my code that will fail with an AssertionError because the file cannot be deleted.
def main(args : Array[String]) : Unit = {
val myFile = new File("c:/tmp/doodah.txt")
var src = Source.fromFile(myFile)
src.getLines.foreach(l => print(l))
val deleted: Boolean = myFile.delete
assert (deleted , "File was not deleted - maybe the stream hasn't been closed in Source")
}
Source has a method called reset however all that this does is recreate the source from the file.
Internally Source creates an underlying BufferedSource that has a close method. However this is not exposed from Source.
I'd hope that Source would release the file handle once the contents of the file had been read but it doesn't seem to do that.
The best workaround I've seen so far is to essentially cast the Source to a BufferedSource and call close.
try {
src.getLines.foreach(l => print(l))
}
finally src match { case b: scala.io.BufferedSource => b.close }
Alternatively I could create a Source from an InputStream and manage the closing myself.
However this seems somewhat dirty. How are you supposed to release the file handle when using Source?
Scala.io._ is a barebones hack created for the sole purpose of supporting the XML library and the compiler. It is badly designed and suffers from many problems. Scala 2.8 will purport an improved version of it, though hardly anything to write home about.
There is an on-going third party effort by interested parties to develop a sound Scala I/O library. It aims to take home the lessons learned by the JDK7 I/O redesign, while providing an Scala-ish API.
Meanwhile... use Java libraries whenever your application stumbles upon the design problems of the present library.
Works in Scala 2.8.x with a little modification. "getLines" -> "getLines()"
...
src.getLines().foreach(l => print(l))
...
scala.io.Source in 2.8.x is better thought out than its counterpart in 2.7.x and it closes the InputStream correctly.
as far as I can tell io.Source is still broken in 2.8 (connections are leaked etc), so people should be discouraged from using it.
As David suggested above, until the replacement lib http://github.com/scala-incubator/scala-io gets merged (probably after 2.8) the best choice is to relay on pure java libs like apache commons-io etc.