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...
Related
I am learning Scala and as part of the journey I had come across two different ways to write your scala class - one with a main method and other without the main method but by extending App (earlier Application is deprecated due to concurrency issues).
I am executing the scripts in Command Line via scala executable as scala <nameOfScript>.scala. I run Scala 2.11.7 in Windows.
I have no issues when running a scala script/class with a main method.
object ObjectWithMainMethod {
def main(args:Array[String]) = {
println("Object with a main() method executed..")
}
}
It produces the following output.
Object with a main() method executed..
But, I don't get the output with its counterpart, which is extending App trait but without the main method.
object AppWithoutMainMethod extends App {
println("AppWithout main() method executed")
}
When I run this scala script, it does not print anything. However, when I looked at the complied .class files via javap utility, I could see the PSVM (public static void main() method) inside.
Am I missing something? Any help on this will be highly appreciated.
If you run scala -help you'll see this comment:
A file argument will be run as a scala script unless it contains only
self-contained compilation units (classes and objects) and exactly one
runnable main method. In that case the file will be compiled and the
main method invoked. This provides a bridge between scripts and standard
scala source.
This explains exactly what you're seeing - the scala command is primarily meant to execute "scripts", or a series of expressions - for quick, interactive evaluation of code snippets. It only runs "applications" (i.e. objects with main method) as a "special case", because it makes sense users will try to use it this way. So:
When you run scala ObjectWithMainMethod.scala, the main method is identified and the command enters this "special case", figuring out that you probably meant for it to work that way
When you run scala AppwithoutMainMethod.scala, even though App has a main method, this isn't identified as the "special case" but just as a series of expressions, so the main method isn't invoked.
If you compile your classes into .class files and run them via java -cp <classpath> <class-name> command, the two will produce identical results.
The same thing works if I run the file without the .scala extension. I am not sure the reason behind this.
scala AppWithoutMainMethod
It produces the following output
AppWithout main() method executed
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.
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)
From the scala compiler help, I would have thought that "-Xprint:MyPhase" would do just that, but despite the fact that the plugin does it's job, and that I know it makes log output, I still don't see any output from coming from scalac when it runs. All I see are "[[syntax trees at end of MyPhase]] ..." Since logging seems to simply involve calling log("..."), I can't imagine what I would be doing wrong in the code that produces the log output. As an ugly work-around I can still do System.out.println(), but if there is a log() method, than I have to assume that it's actually meant to do something ...
-Ylog:<phase>
Use scalac -Y to see all the "private" options.
I am playing with Scala. What I need is just a brunch of function definitions, but in Eclipse I can only create .scala files for which a function def must be inside an object or class.
But I see a Scala script online, here, which does not use an object to wrap all the functions.
It is of course ok for me to use an object to wrap all my functions, but I am just wondering whether it is required. Thanks!
But I see a Scala script online, here, which does not use an object to wrap all the functions.
Note that in this case, the functions can't be called from other files (they are wrapped in an object with compiler-generated name when run). If you "need just a brunch of function definitions", this is likely not what you want :) AFAIK, Scala IDE doesn't support script files at the moment, but you could log a feature request here.
Yes, in Eclipse you need to wrap everything in an object or a class.
You can edit Scala scripts in Eclipse as long as you wrap the code in an object and avoid the Shebang. Just run the script with scala -i scriptName.scala -e "Main.main(args)" (providing you have the "bin" folder of scala distribution on your path).
foo.scala:
object Main extends App {
println ("foo")
}
To run it:
scala -i foo.scala -e "Main.main(args)"
To my knowledge it isn't possible to write functions or variables completely outside of scope. That said it is possible to write them outside of class/object definitions. You just have to wrap them in a package object. What's happening is basically that instead of tying the function/variable to a given class or object, you tie it to a package. Example:
package test
package object inside {
def hello = println("Hello from outer space!")
class Foo {
hello // call the function from the package
}
}
Now, when you construct Foo, you should get printed "Hello from outer space!".
Without knowing completely what I'm talking about, I could imagine that the script version you mentioned above works, because the script is being run in some kind of an environment. So imagine some class loading the script, then wrapping it into an object and the running it. That would imply a situation somewhat like the one above: the functions still "belong" to somewhere.