Friday, January 18, 2013

Goodby Scala + Gradle + emacs!

Well, that was short lived... I understand that ensime works better with sbt, but I'm restricted in my tool choices. And I can't figure out how to get ScalaTest to run within ensime directly. I must for now set aside ensime and get some work done.

Thursday, January 17, 2013

Scala + Gradle + emacs

It's been a while since I've been able to use emacs as a primary development environment. Since the eclipse development environment isn't all that great for scala, I thought I'd see how well emacs served in that role. First we'll set up emacs and scala. These directions are based on this blog post.
  1. Install scala-mode2. The remainder of the post assumes you have used the preferred installation method, the emacs package manager.
  2. Download ensime and install it in ~/.emacs.d
  3. Add the following to ~/.emacs.d/init.el (or ~/.emacs if you prefer):
    (add-to-list 'load-path "~/.emacs.d/ensime/elisp")
    (require 'scala-mode2)
    (require 'ensime)
    (add-hook 'scala-mode-hook 'ensime-scala-mode-hook)
  4. Once you have a .ensime file for your scala project, you can run M-x ensime, and you're off!
Ideally, you'd be generating your .ensime from a build.gradle (or build.sbt or whichever tool you prefer) rather than writing it from scratch. From gradle, you would follow the directions for the gradle-ensime plugin. The directions in the  project aren't particularly good, and even though it has a configuration that doesn't match your general project specification, things still seem to work. Here's the step-by-step:
  1. Download gradle-ensime.
  2. In gradle-ensime, run ./gradlew install
  3. In your build.gradle, add the following towards the top of the file:
    buildscript {
      repositories { mavenLocal() }
    
      dependencies {
        classpath group: 'net.coacoas', name: 'gradle-ensime', version: '0.1.0-SNAPSHOT'
      }
    }
    apply plugin: 'ensime'
  4. In your project directory, now run <gradle-ensime-dir>/gradlew ensime
  5. You should now have a .ensime file that you can use when you M-x ensime, in emacs.

[Edit: ensime prefers scala-mode2 over scala-mode, so the instructions now reflect that.]

Wednesday, January 2, 2013

Types in Scala

Writing a toy program in Scala is turning out to be surprisingly difficult. I think I'm running into a something that makes Scala fundamentally different from many other languages I've programmed with: Scala types are surprisingly complex. I don't necessarily mean this in a negative way.

I've so far tried manipulating two types in my program: maps and streams. Maps can be mutable or immutable. The latter seems to be the default behavior. When I tried creating an immutable map from a mutable one, the compiler complained with an obscure message:

scala.collection.mutable.Map[String, String]().toMap()

type mismatch; found: scala.collection.immutable.Map[String,String]; required: <:<[(String, String),(String, String)]

The argument doesn't seem to be used in the implementation of toMap() though. Instead of chasing down this mystery, for my program, I have used Map.newBuilder, as has been used in toMap().

But now that I'm looking at this again, I notice that:
  1. I should have called scala.collection.mutable.Map[String, String]().toMap.
  2. The required argument is a generic transformer from the map elements (if the map is viewed as a collection of pairs) to map entries. This is a vacuous transformation. There's more information in this StackOverflow thread.
Streams seem fundamentally different data structures from Java streams. Looking through the API, I don't see any operations on scala streams analogous to the low level streams, such as file streams, that Java provides. I might have missed something. Otherwise, it would seem to me that Scala isn't really a "full" language, in that there are basic operations that it expects you to implement through Java. Perhaps this isn't that different from clojure either, which explicitly aims to be a hosted language.