views:

106

answers:

3

What kind of constructs need 'scalac' compile and how to make an equivalent that will work in interpreter?

Edit: I want to use scala instead of python as a scripting language. (with #!/usr/bin/scala)

+1  A: 

I think everything in Scala will work from the interpreter as well (which I believe just calls the compiler under the hood anyway).

Do you suspect something to not work? Or is this a trick/interview question (I suppose anything that want to directly interact with the class loader or class files may behave differently in the two environments, but I have no idea really).

Thilo
+2  A: 

EDIT: after reading your question again, I have to admit, that I didn't really answer it ;). But maybe it still helps.

I know of two limitations of interpreter (or REPL), when it comes to loading scala files (in order to interactively test them).

  • You can't load scala files with package definitions in them. REPL complains and does not load all class is the scala file to be loaded. It read that it has to do with the fact that files that are loaded into the REPL are treated as an object . . . which of course can't have any package definitions in them.
  • REPL is strange (or a little bit unpredictable) when there are class files of loaded scala files on the classpath. Check out this question by myself and especially my 2 last comments to the second answer.

Furthermore there is a problem with circular dependencies, that I don't know a workaround for: Suppose there is a Class A that uses Class B which again needs A to do it's job. Of course you can't define A since there is no definition of B and vice versa. Providing a dummy for one of those doesn't work either:

scala> class A {                                           
 |   def alterString(s:String) = s                     
 |   def printStuff(s:String) = println(alterString(s))
 | }                                                   
defined class A

scala> class B {                                           
 |   val prefix = "this is a test: "                   
 |   def doJob() = new A() printStuff "1 2 3"            
 | }
defined class B

scala> class A {
 |   def alterString(s:String) = new B().prefix + s
 |   def printStuff(s:String) = println(alterString(s))
 | }
defined class A

scala> new B().doJob()
1 2 3

scala> 

Although I already provided a newer definition of A, class B still used the one that was present when I defined it.

Agl
+4  A: 

You ought to be able to do anything in the REPL that you can do in outside code. Keep in mind that:

  • Things that refer to each other circularly need to be inside one block. So the following can't be entered as-is; you have to wrap it inside some other object:

    class C(i : Int) { def succ = C(i+1) }
    object C { def apply(i: Int) = new C(i) }

  • The execution environment is somewhat different, so benchmarking timings will not always come out the same way as if you run them from compiled code.

  • You enter the execution path a different way; if you want to call a main method, though, you certainly can from inside the REPL.

  • You can't just cut-and-paste an entire library into the REPL and have it work exactly like the library did; the REPL has a different structure than normal packages do. So drop the "package" declarations during testing.

Rex Kerr
Related to your note about forward references, you also have to wrap companions in an object: http://stackoverflow.com/questions/3551981/is-it-possible-to-define-companion-classes-modules-in-the-scala-interpreter
Aaron Novstrup