The contents of myfile.scala are as follows :
// println("print this line")
object myObj {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
If I run : scala myfile.scala, it prints : Hello, world
If I uncomment the first println stmt, and run : scala myfile.scala,
it only prints : print this line ,
and does not print hello-world stmt.
Why is this so? I find it very confusing. I tried to search the archives, but could not find any answers.
When the scala command sees a top level statement (not in a class or object) in the file, it runs the file as a script, starting at the first line and moving down. You main method never gets called because you never call it, just define it. When your file doesn't contain any top level statements but it does contain a main object, it will run the main method as the entry point to the program.
Related
I am trying to use the worksheet functionality of Intellij. I have this simple code:
object Timer {
// this function takes another function as an argument.
// that function takes no args, and doesn't return anything.
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread.sleep(1000) }
}
// the function we'll pass in to oncePerSecond.
// this can be any function that takes no args and doesn't
// return anything.
def timeFlies() {
println("time flies like an arrow ...")
}
// the main() method, where we pass timeFlies into oncePerSecond.
def main(args: Array[String]): Unit = {
oncePerSecond(timeFlies)
}
}
Why doesn't it run? I don't see "time flies like an arrow" when it executes.
If you want to run this method inside worksheet you shouldn't put it in main method but:
oncePerSecond(timeFlies)
without anything. In this Timer object.
Edit:
If you want to run it from a console you can use scalac and scala:
scalac Timer.scala
scala Timer
Or you can create a simple sbt project or use another build tool.
Edit2: Previously I didn't see that you have one more question. Your code doesn't work because in practice you create a method main without using it. In a worksheet, you need to use a method to see the result. So if you put in object:
val a = 1
and you run this worksheet you can see that it's evaluated on the right side (in the right window).
The same situation is with a method. If you create some method you can see that method is created. To see the result you only need to use this method and run the worksheet.
I am trying to compile and execute a "hello world" program using twitter util-eval library. But not able to get results printed.
My intention is not just to compile and execute hello world example, large scala files with dependencies should compile and run.
import com.twitter.util.Eval
object ScalaCompiler3 {
def main(args: Array[String]): Unit = {
val eval = new Eval()
val fileContents = "class Test {\n\n println (\"Hello World!\")\n\n}"
val compile = eval.apply[Unit](fileContents)
println(compile)
}
}
How do I execute the code and see the results? am not able to get proper API documentation for util-eval. Using util-eval_2.11-6.43.0.jar taken from maven
As erip mentioned in the comments, the source string you're compiling makes a class, Test, but since you never instantiate the class it never runs the code within.
If you replace:
val fileContents = "class Test {\n\n println (\"Hello World!\")\n\n}"
with:
val fileContents = "println(\"Hello World!\")\n\n}"
That will execute the code you're looking to execute. Best of luck with your project!
I'm trying to write an integration test for a small command line app I'm writing with Scala and SBT. My app would usually be run from the SBT prompt like so:
> run "my arg"
The argument "my arg" is accessed in the app with args(0). For an integration test how can I simulate calling run with an argument and asserting console output?
Your app needs to have an object with main method that takes Array[String] as parameter.
It looks like this
object Main extends App {
print("hi, " + args(0))
}
or like this
object Main {
def main(args: Array[String]) = print("hi, " + args(0))
}
Anyway you definitely have this kind of entry point if you can do > run "my arg" in sbt.
It is just an object with a method called main that you can call wherever you want. Just import it and use:
Main.main(Array("my arg"))
that would print the text to the console when executed. We need to redirect the console output to some other stream to be able to verify it.
Using answer from Redirect stdout in another thread you can come up with something like this:
val baos = new ByteArrayOutputStream
val ps = new PrintStream(baos)
Console.withOut(ps)(Main.main(Array("my arg")))
val output = baos.toString
And you can do all sort of tests on output value
You can then create a helper method to handle this for you
def outputFor(args: String*): String = {
val baos = new ByteArrayOutputStream
val ps = new PrintStream(baos)
Console.withOut(ps)(Main.main(args.toArray))
baos.toString
}
And then easly test your app
"My app" should "greet me" {
outputFor("harryg") shouldBe "hi, harryg"
}
Just to clarify, the whole solution has nothing to do with sbt itself, we directly call the program in a similar way that sbt would do it.
I have a requirement to println(something) but doesn't println anything and no new line printed, how can I do that in Scala?
What should 'something' above in println be so that it satisfies my requirement?
scala> Console.setOut(new java.io.PrintStream(new java.io.OutputStream() { def write(b: Int) {} }))
scala> println("test")
scala>
I'm just relating Florian Hars reply from the google scala-user mailing list, which seems to better frame the point.
Let me restate your problem: you have an assignment where you need to ignore comments while parsing some code source file.
Actually you have a main definition to test the assignment which prints out the result of parsing the source file, and you want the println statement to ignore the parsed comments, so the teacher's condition will be met.
If this is the case, then the "correct" solution would not be to find a way to prevent println to print, but to modify the parser/lexer to avoid producing a parsed token when it encounters a comment.
The other way would just be a "trick" to get the assignment right by exploiting a particular "code configuration"...
println(...) will always print a newline, no matter what argument you pass it. There is no way to prevent it from printing a newline.
Well... there's ofcourse the following trick, but it's not very practical.
class Magic {
override def toString = throw new RuntimeException
}
// Will not print a newline, but will throw an exception
println(new Magic)
// So you'll need to catch it
try {
println(new Magic)
} catch {
case e: RuntimeException => // Ignore the exception
}
// Hey, we're here and no newline was printed!
if you're still running the scala interpreter, you can exit it by entering the :quit command. Put this into a file named hello.scala:
println("Hello, world, from a script!")
then run:
scala hello.scala
And you should get yet another greeting:
Hello, world, from a script!
I am trying to understand the 4th rule on Precedence on Bindings on page 93 in Joshua Suareth's book Scala in depth.
According to this rule:
definitions made available by a package clause not in the source file where the definition occurs have lowest precedence.
It is this rule that I intend to test.
So off I went and tried to follow Josh's train of thought on Page 94. He creates a source file called externalbindings.scala and I did the same, with some changes to it as below
package com.att.scala
class extbindings {
def showX(x: Int): Int = {
x
}
object x1 {
override def toString = "Externally bound obj object in com.att.scala"
}
}
Next he asks us to create another file that will allow us to test the above rule. I created a file called precedence.scala:
package com.att.scala
class PrecedenceTest { //Josh has an object here instead of a class
def testPrecedence(): Unit = { //Josh has main method instead of this
testSamePackage()
//testWildCardImport()
//testExplicitImport()
//testInlineDefinition()
}
println("First statement of Constructor")
testPrecedence
println("Last statement of Constructor")
def testSamePackage() {
val ext1 = new extbindings()
val x = ext1.showX(100)
println("x is "+x)
println(obj1) // Eclipse complains here
}
}
Now, Josh is able to print out the value of the object in his example by simply doing the <package-name>.<object-name>.testSamePackage method on the REPL.
His output is:
Externally bound x object in package test
In my versions, the files are in Eclipse and I have my embedded Scala interpreter.
Eclipse complains right here: println(obj), it says: not found value obj1
Am I doing something obviously wrong in setting up the test files?
I would like to be able to test the rule I mentioned above and get the output:
Externally bound obj object in package com.att.scala
I haven't read the book, thus I'm not really sure if your code shows what the book wants to tell you.
Nevertheless, the error message is correct. obj1 is not found because it doesn't exist. In your code it is called x1. Because it is a member of extbindings you have to access it as a member of this class:
println(ext1.x1)
If x1 is defined outside of class extbinding, in scope of package com.att.scala, you can access it directly:
println(x1)
If it is defined in another package you have to put the package name before:
println(com.att.scala2.x1)
To simplify some things you can import x1:
import ext1.x1
println(x1)
Finally a tip to improve your code: name types in UpperCamelCase: extbindings -> Extbindings, x1 -> X1
If you replace a singleton object with a class, you will need to create an instance of that class.