A Poor Man’s Guide to Getting Started With Scala

Want to get started with Scala, but not keen on using fancy IDEs nor have the cash to afford a nice Mac Powerbook and TextMate? Then this guide is for you! I’ll illustrate how to get a nifty scala development environment up and running on a system running Ubuntu with minimal hassle… and best of all completely cash free.

Step One: Getting the Prerequisites

To start with, you of course need java… how you get this is up to you, but my preferred method of getting it is cracking open a terminal and apt-getting the sun-java5-jdk.

sudo apt-get install sun-java5-jdk

Next, not having TextMate available on linux, we’ll settle on the next best thing and install Gedit.

sudo apt-get install gedit

Gedit can be as lame as notepad at first glance, but don’t be easily fooled, you just need to configure it a little and install a few plugins. See my earlier blog post on how to Pimp My Gedit.

Also, to make things a little prettier while editing scala files and getting the much needed syntax highlighting, I recommend installing the scala lang file found here. Here’s some quick copy and paste commandline commands to get them installed quickly:

sudo wget http://lousycoder.com/blog/uploads/scala-mime.xml -O /usr/share/mime/scala-mime.xml
mkdir ~/.gnome2/gtksourceview-1.0/
mkdir ~/.gnome2/gtksourceview-1.0/language-specs
wget http://lousycoder.com/blog/uploads/scala.lang -O ~/.gnome2/gtksourceview-1.0/language-specs/scala.lang

If all goes well, you should be able to open gedit, create a file with the scala extension, and see syntax highlighting like this:

If the syntax color doesn’t show up, look under Edit -> Highlight Mode -> Sources and select Scala.

Step Two: Install Scala

This one, like the previous step, is rather easy. You can either go get Scala off of the website or simply go back to the terminal and run

sudo apt-get install scala

Run scala from the commandline to make sure everything is working good. Now let’s really get cracking!

Step 3: Making Barebones Scala Development Painless

When I first started trying to develop Scala using just gedit and a terminal, it was about as painful as writing and running C++ code in vim. ARGH!!!

Thankfully, there’s a handy project on google code called simple-build-tool which makes your environment complete. Following the Setup instructions on the site, download the jar for it and place it in ~/bin (you can put it anywhere, but I find it easier here), and write a bash script named sbt to execute it. Here is the contents of mine:

#!/bin/bash
java -Xmx512M -jar `dirname $0`/sbt-launcher-0.5.4.jar "$@"

I cannot get the bash script example they give to work without renaming the jar to be version-less… I’m not a fan having version-less jars laying around though, so I included the version name. YMMV.

You also might be like me and not have ~/bin set up at all… so you’ll have to create the directory yourself and add it to the path. If you’re using bash, just add the following to the bottom of your ~/.bashrc file:

if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

Now if you open a new terminal or restart bash, you should be able to run sbt from any directory. Fire up gedit, make sure you have the multi-terminal plugin enabled, and in the terminal create a directory for your project… for this example we’ll call it HelloWorld. Move into the directory and run sbt. After prompting you whether you want to create a new project it’ll ask you a few questions, such as project name (HelloWorld), organization (example) and other prompts that you can just use the defaults for. You should then see some action take place (maven repository setup, directory structure creation, etc) that looks a lot like this:

Congratulations! You’ve just set up your first scala project using sbt. Now let’s actually set up what we need to write our code BDD style by adding some dependencies like Specs.

Step 4: Dependency Management

At it’s core, sbt uses maven to resolve dependencies, but you can configure those dependencies in a scala file. Since I stated earlier that I like to use specs, I’m going to illustrate creating a ProjectDefinition file to include specs as a test dependency. I’ll have to create a new directory named build under the directory project, and then create the file HelloWorld/project/build/HelloWorldProject.scala with the following contents:

import sbt._

class HelloWorldProject(info: ProjectInfo) extends DefaultProject(info){
  val specs = "org.scala-tools.testing" % "specs" % "1.6.0" % "test->default"
}

Now to get this picked up, I need to return to the console, run reload to get my project definition picked up and then update to resolve the new dependencies. You should see a bit of maven resolution fly by the console and when it’s over a new directory named lib_managed has been created with specs-1.6.0.jar resting within it. :)

Step 5: Can We Get Started Already!?

Now it’s finally time to illustrate writing some code using this setup… the infamous HelloWorld example. Since we’re doing BDD, we’ll start by writing a spec to illustrate how our HelloWorld object will behave by creating our first file, HelloWorld/src/test/scala/HelloWorldSpec.scala:

import org.specs._

object helloWorld extends Specification {
  "'hello world' has 11 characters" in {
    "hello world".size must_== 11
  }
}

Naturally, it’s nice to start with something simple to see if everything is configured. From the sbt console, just run test and you should see a nice passing example:


[info] == helloWorld ==
[info] specifies
[info] + 'hello world' has 11 characters
[info]

Unfortunately it can be a little noisy, but the last couple lines of the console output from running the specs will indicate if the examples are passing or failing.

Since we have confirmed everything is working, let’s rewrite our spec to actually use a dumb HelloWorld class:

import org.specs._

object helloWorld extends Specification {
  "should combine greeting and greetee" in {
    val greeter = new HelloWorld("Hello", "Dude")
    
    greeter.greet() mustEqual "Hello Dude"

  }
}

And an empty class under src/main/scala/HelloWorld.scala to rid ourselves of compilation errors:

class HelloWorld(greeting:String, greetee:String){
  def greet():String = {
    ""
  }
}

Rerun the test command, watch all the console output fly by and we’ll quickly discover a failing example:


[info] == helloWorld ==
[info] specifies
[info] x should combine greeting and greetee
org.specs.specification.FailureExceptionWithResult: '' is not equal to 'Hello Dude'

Now let’s go ahead and write the code needed to make the example pass:

class HelloWorld(greeting:String, greetee:String){
  def greet():String = {
    greeting +" "+ greetee
  }
}

Re-run test one last time, and we should finally have a validly passing example and some code to illustrate a simple project setup. Pat yourself on the back… you’ve taken your first steps with scala. Maybe now you’re ready to make an actual web application using the HelloLiftExample. :)

Closing Thoughts

Believe it or not, I’ve been hacking scala code in an environment like this for a couple weeks now… although at first you kind of miss the compilation error underlines of a proper IDE, you get kind of used to it. i usually have 3 terminals open within gedit while developing… one with sbt running in it so I can run commands, one with scala running so I can just try something out if I have an idea, and one terminal open in the project directory so i can quickly get at files to edit them rather than click through sub directories.

Now, if I could just have something like ZenTest for ContinuousTesting my environment would be complete…

  • Mark Harrah

    Hi James!

    Nice to see articles like this. Sorry that the script didn’t work as is for you. What was the problem exactly? I’d like to clarify the documentation.

    sbt uses Apache Ivy for dependency management, although it can (and does) retrieve from Maven repositories. I think you want to link to LibraryManagement#Inline_Declarations instead of ScalaJars since ScalaJars is about something else.

    You might know this, but the ‘console-quick’ action drops you to the Scala interpreter with your project’s classpath. The ‘console’ action does this too but runs ‘compile’ first. (See the RunningSbt page)

    You might also find the TriggeredExecution page useful, which describes continuous execution/testing. Unfortunately this feature was broken in 0.5.3, so you’ll want to use 0.5.4 by doing:
    set sbt.version 0.5.4
    reboot

    Thanks again for the writeup!

    -Mark

  • Pingback: links for 2009-09-24 « Bloggitation