Tuesday, February 22, 2011

ScalaIDE vs Me

I like Eclipse, I like functional programming languages, and I hear great things about Scala so I thought I'd try it out by way of the ScalaIDE.

Initial installation was a little painful. The (experimental) Eclipse 3.6 Helios update site wouldn't work so I grabbed the latest Eclipse 3.5 Galileo (Java Dev, SR2) and tried to use the update site for that. Sadly this just gave me a "we hate your certificate" message with no option to trust anyway and aborted the install process. Arglefarg. Downloading the zip file of the update site and pointing Eclipse at the provided content.jar also produced a "we hate your certificate" message but this time there was an option to trust anyway and finally the damn thing got installed. Finally!

Having the IDE installed adds New Project>Scala Wizards>Scala Project. This sets up the .classpath and .project files appropriately for Scala. I like editing these files manually at times so I tend to inspect them whenever I try a new project type.

.classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
 <classpathentry kind="src" path="src"/>
 <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 <classpathentry kind="output" path="bin"/>
</classpath>
.project
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
 <name>helloscala</name>
 <comment></comment>
 <projects>
 </projects>
 <buildSpec>
  <buildCommand>
   <name>org.scala-ide.sdt.core.scalabuilder</name>
   <arguments>
   </arguments>
  </buildCommand>
 </buildSpec>
 <natures>
  <nature>org.scala-ide.sdt.core.scalanature</nature>
  <nature>org.eclipse.jdt.core.javanature</nature>
 </natures>
</projectDescription>
Using the commandline interpreter hello world looks like this:
println "hello, world"
However, ScalaIDE doesn't like that; it demands a proper object declaration:
object helloapp {
  def main(args : Array[String]) = println("Hello, World")
}
ScalaIDE installs the expected keyboard shortcuts (eg Alt+Shift+X, S to run a Scala app) but sadly it doesn't actually work; the IDE just spits out no class def if you try to run:
java.lang.NoClassDefFoundError: helloapp
Caused by: java.lang.ClassNotFoundException: helloapp
 at java.net.URLClassLoader$1.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
Exception in thread "main" 
A little poking around revealed that the projects /bin directory had nothing in it. As this is where it looks for .class files the NoClassDef issue makes sense ...except that the file I tried to run was valid and should have compiled into /bin damnit!

After playing around a bit I finally figured out that the first file I created (the minimal hello world that the IDE doesn't like) doesn't compile in the IDE and apparently that prevented other files added to the project from being compiled either! WTF! In any case, once the offending file was fixed and the Problems window reports no Scala issues the expected .class files show up in /bin and it becomes possible to run as Scala App from within Eclipse.

In painful detail:
  1. Create a few valid Scala files in Eclipse, with Project>Build Automatically turned on
    1. .class files show up in the /bin dir, we can run as Scala App just fine
  2. Add a Scala file with a problem
    1. The IDE reports it in Problems; we can run the other files as Scala App just fine (because their .class files are in /bin)
    2. Other (valid) files can be run OK ... unless you do a Project>Clean, in which case all your .class files are wiped out and none are replaced because one bad file = no class files are created for any file
    3. Additionally, if you modify a valid file (in a valid way) it's .class file is removed but not replaced, again because apparently one bad file = no class files for all
It's not that big of a deal as I usually keep my files in a compilable state, but it definitely gives the impression that the tool (ScalaIDE, not Scala itself) is still pretty immature. Apparently such problems plague others as well - http://www.assembla.com/spaces/scala-ide/tickets/1000073-java-lang-noclassdeffounderror-when-launching-application. Amusingly other features that one might think of as "advanced", such as refactor support for extract variable and the like are working for me, it's just the basic compilation management that seems weak.

On the plus side Scala itself is awesome. Anytime a language lets me pass a function it makes me happy ;)
object fizzbuzz {
  def main(args : Array[String]) = {
    //OMG I can pass a function like a first class citizen!
    //Damnit Java ... let me use functions this way
    (1 to 100).foreach(fizzbuzz)
  }
  
  def fizzbuzz(i : Int) = {   
    val isFizz =  i % 3 == 0
    val isBuzz =  i % 5 == 0
    if (isFizz) print ("Fizz")
    if (isBuzz) print ("Buzz")
    if (!isFizz && !isBuzz) print (i)
    println
  }
}

I hope the ScalaIDE stabilizes a bit because so far Scala looks awesome and I am fond of working in Eclipse.

2 comments:

Rod said...

Issue is filed with ScalaIDE; http://www.assembla.com/spaces/scala-ide/tickets/1000242

Unknown said...

You should really use IntelliJ IDEA (it has a free edition) and its Scala plugin.

Post a Comment