Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reload a class or package in Scala REPL?

I almost always have a Scala REPL session or two open, which makes it very easy to give Java or Scala classes a quick test. But if I change a class and recompile it, the REPL continues with the old one loaded. Is there a way to get it to reload the class, rather than having to restart the REPL?

Just to give a concrete example, suppose we have the file Test.scala:

object Test { def hello = "Hello World" } 

We compile it and start the REPL:

~/pkg/scala-2.8.0.Beta1-prerelease$ bin/scala Welcome to Scala version 2.8.0.Beta1-prerelease (Java HotSpot(TM) Server VM, Java 1.6.0_16). Type in expressions to have them evaluated. Type :help for more information.  scala> Test.hello res0: java.lang.String = Hello World 

Then we change the source file to

object Test {   def hello = "Hello World"   def goodbye = "Goodbye, Cruel World" } 

but we can't use it:

scala> Test.goodbye <console>:5: error: value goodbye is not a member of object Test        Test.goodbye             ^  scala> import Test; <console>:1: error: '.' expected but ';' found.        import Test; 
like image 761
Rex Kerr Avatar asked Mar 18 '10 17:03

Rex Kerr


People also ask

How do I run a scala code in REPL?

We can start Scala REPL by typing scala command in console/terminal. Let's understand how we can add two variable using Scala REPL. In first line we initialized two variable in Scala REPL. Then Scala REPL printed these.

How does scala REPL work?

The Scala REPL is a tool (scala) for evaluating expressions in Scala. The scala command will execute a source script by wrapping it in a template and then compiling and executing the resulting program.

What is REPL in scala?

The Scala REPL (“Read-Evaluate-Print-Loop”) is a command-line interpreter that you use as a “playground” area to test your Scala code.

How do I run a shell in scala?

To run Scala from the command-line, download the binaries and unpack the archive. Start the Scala interpreter (aka the “REPL”) by launching scala from where it was unarchived. Start the Scala compiler by launching scalac from where it was unarchived.


2 Answers

There is an alternative to reloading the class if the goal is to not have to repeat previous commands. The REPL has the command

:replay 

which restarts the REPL environment and plays back all previous valid commands. (The invalid ones are skipped, so if it was wrong before, it won't suddenly work.) When the REPL is reset, it does reload classes, so new commands can use the contents of recompiled classes (in fact, the old commands will also use those recompiled classes).

This is not a general solution, but is a useful shortcut to extend an individual session with re-computable state.

Note: this applies to the bare Scala REPL. If you run it from SBT or some other environment, it may or may not work depending on how SBT or the other environment packages up classes--if you don't update what is on the actual classpath being used, of course it won't work!

like image 76
Rex Kerr Avatar answered Sep 18 '22 07:09

Rex Kerr


Class reloading is not an easy problem. In fact, it's something that the JVM makes very difficult. You do have a couple options though:

  • Start the Scala REPL in debug mode. The JVM debugger has some built-in reloading which works on the method level. It won't help you with the case you gave, but it would handle something simple like changing a method implementation.
  • Use JRebel (http://www.zeroturnaround.com/jrebel). JRebel is basically a super-charged class reloading solution for the JVM. It can handle member addition/removal, new/removed classes, definition changes, etc. Just about the only thing it can't handle is changes in class hierarchy (adding a super-interface, for example). It's not a free tool, but they do offer a complementary license which is limited to Scala compilation units.

Unfortunately, both of these are limited by the Scala REPL's implementation details. I use JRebel, and it usually does the trick, but there are still cases where the REPL will not reflect the reloaded class(es). Still, it's better than nothing.

like image 38
Daniel Spiewak Avatar answered Sep 18 '22 07:09

Daniel Spiewak