You are currently browsing the tag archive for the ‘scala’ tag.

At work we recently completed a task to generate a datafile of locations mapped to nearby locations. Our input is a Postgres table of location data, including name, latitude and longitude. Our target output is a YAML file of each location mapped to those locations which are geographically close.

With the PostGIS extension, PostgreSQL has excellent support for calculating the distance between locations, so our calculations were delegated to the SQL queries. Essentially the query joined each location with every other location and excluded those which exceeded our distance threshold (for example, 25,000 metres).

The task was implemented in Rake. The execution time was in the order of 8 hours. It was assumed that the majority of time was needed for Postgres to perform the GIS calculations. Not so.

I reimplemented the task in Scala using Scweery. The Scala version differs from the rake task in several ways. It is strongly typed (as necessitated by the language) and, apart from IO operations, purely functional (my personal preference). It also used JDBC instead of ActiveRecord. Apart from these differences the algorithm is identical to its Ruby counterpart.

So did the Scweery/Scala version outperform Rake? Yes, without a doubt. /usr/bin/time reports that the Scala version was completed in 8m, 55s. That’s at least 50 times quicker. Importantly, it turns what was an overnight task into what is now a coffee break task.

Advertisements

My latest objective has been to construct a DSL for asserting whether a chess piece, within the context of a game, can make a particular move. I have managed to construct a syntax that resembles:

pawn canMove Straight towards Black

Some alternative examples are :

pawn canMove Straight by 2 towards Black
pawn canMove Diagonally towards (Black, King)

With this syntax it is possible to construct executable specifications using Specs that read:

"a pawn that has already been moved and is not blocked" should {
    "be able to move one square towards opposite colour" in {
      pawn canMove Straight towards Black must beTrue
    }
}

Operator notation is what enables the building of this kind of syntax. It is the ability to omit the dot and parentheses on any function call with exactly one parameter. It is not possible to achieve this when there is 2 or more parameters (both dot and parentheses are required) or when there are zero (the parentheses are optional, but the dot is required).

Without operator notation, the initial example above would be written as:

  pawn.canMove(Straight).towards(Black)

Straight-line movement

In order to facilitate this structure, Piece.canMove(m: Movement) implies an instance of CanMove (a case class). CanMove.towards(o: Orientation) decides whether the move can proceed. Both Straight and Black are case objects.

class Piece(val colour: Colour, val role: Role, val position: Position) {
  def canMove[M >: Movement](m: M): CanMove[M] = CanMove(m, this)
}

case class CanMove[M >: Movement](m: M, p: Piece) {
  var dist = 1
  def towards(o: Orientation): Boolean = {
    m match {
      case Straight => p.role match {
        case Pawn => dist == 1 && o.equals(opposite of p.colour)
        case _ => false
      }
      case _ => false
    }
  }
}

At this stage, only the behaviour for “a pawn that has already been moved and is not blocked” has been specified. As such it is a simple case statement. If the movement is Straight and the piece is a Pawn, check that it is trying to move 1 space and that it is moving toward the opposite coloured side.

Diagonal Movement

Queries regarding diagonal movement require additional thought, as the direction is a composite of both Colour (Black or White) and Role with Orientation (Queen or King). In this case, a towards function is provided that takes a Tuple2 of these two parameters.

def towards(o: Tuple2[Colour, Role with Orientation]): Boolean = false

The function currently returns false, because there is no specification written yet that would require it to be true. Following BDD means the simplest possible implementation that would work is in place.

Using a Tuple2 instead of two input parameters permits operator notation to be used. That is, it is a single parameter comprised of two values. Although denoting the tuple does require the use of parentheses and a comma, but I think the effect is still readable.

"a pawn that has already been moved and is not blocked" should {
  "not be able to move diagonally towards black queen" in {
    pawn canMove Diagonally towards (Black, Queen) must beFalse
  }
}

Movement greater than 1 square

In order to support movement in a direction over multiple squares, the CanMove class is provided a by(distance: Int) function that sets the distance on the instance, and returns the instance again for a chained function call.

def by(distance: Int) = {
  dist = distance
  this
}

This permits the interspersing of ‘by n‘ as an optional term. On the downside, it also permits the illogical interspersing of multiple calls to ‘by n‘. Such as:

pawn canMove Straight by 1 by 9 by 4 towards Black

The pawn movement specification for this function utilises ScalaCheck to test a range of conditions of n from 2 upwards. This testing tool executes the specification with 100 arbitrary values of n that are 2 or greater.

"a pawn that has already been moved and is not blocked" should {
  "not be able to move more than one square towards opposite colour" in {
    forAll { n: Int => n >= 2 ==>
            (pawn canMove Straight by n towards Black equals false)
    } must pass
  }
}

Source code

The complete code (as a work in progress) lives on github. I welcome any advice on how to improve the approach I’ve taken.

Google App Engine recently added support for Java. As a beautiful side-effect of this, Scala is supported. Unfortunately the delicious Scala-based web framework Lift does not work there, due to sandbox constraints in GAE around thread creation and JDBC access. (Though there is hope that David Pollak will get core Lift working with GAE as early as mid April*).

I’ve just uploaded a hello world app that is written with a JSP delegating to Scala. (It’s not worth clicking through to, but it is here if you need proof). Here is what I needed to do, once I had signed up and downloaded the SDK.

First you need to create the right project structure. You can get it automagically if you are using the Eclipse plugin, but I find that particular IDE to be a choking hazard. Here’s the structure I created manually.

  • project_root
    • src
    • web
      • WEB-INF
        • classes
        • lib

The one-and-only page is the JSP war/index.jsp. It delegates to the Scala class.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="au.com.loftinspace.scalachess.LoginSnippet" %>
<html>
  <body>
    <h1>Just a test</h1>
    <%= LoginSnippet.render(request) %>
  </body>
</html>

The custom Scala object providing the XHTML snippet to display is defined in LoginSnippet.scala

package au.com.loftinspace.scalachess

object LoginSnippet {
    def render(request: _root_.javax.servlet.http.HttpServletRequest) = {
        import _root_.com.google.appengine.api.users._
        val userService = UserServiceFactory.getUserService
        val user = userService.getCurrentUser

        if (user == null) {
            <p>Hello! <a href={userService.createLoginURL
                (request.getRequestURI)}>Sign in</a>
                just for kicks.</p>
        } else {
            <p>Hello, {user.getNickname}! Now you can
                <a href={userService.createLogoutURL(
                request.getRequestURI)}>sign out</a> again.</p>
        }
    }
}

Scala classes need to be compiled to web/WEB-INF/classes (just as Java classes would). When compiling the class I required the following on the classpath:

  • appengine-java-sdk/lib/shared/geronimo-servlet_2.5_spec-1.2.jar (for HttpServletRequest); and
  • appengine-java-sdk/lib/user/appengine-api-1.0-sdk-1.2.0.jar (for the User functionality)

Some jars need to be deployed with your application. This simply means placing them in web/WEB-INF/lib. The jars I required were:

  • scala-library.jar (for the scala -> java bridging objects you get when scala is compiled, and several classes from scala.xml._ which I have used implicitly by defining the inline XML in the render function).
  • appengine-api-1.0-sdk-1.2.0.jar (which surprises me a little, as I thought GAE could provide this itself)

This is a reworked version of login as seen in the SDK’s demo application GuestBook. It is worth noting that the User functionality allows any username when running under the SDK’s development server, but integrates with Google account authentication once published to GAE.

Update: David Pollak – In case you missed it, Lift *does* run on the Google App Engine http://lift-example.appspot.com/index