Friday, December 10, 2010

Klingon Scala

English is a "subject-verb-object" language.  This denotes the ordinary order of words in an English sentence.  For example, "He loves her," reveals his feelings, but not hers.  When we write code in an object oriented language, we tend to choose words that reflect this practice.

In Scala, given a Set ns of Integers, we can use the Set's contains method to ask whether a given number is in the Set.

  val ns = Set(8, 15, 17)
  println(ns contains 42)  //false
  println(ns contains 17)  //true

In a sense, contains is a binary operator that carries ordered pairs to Booleans.  We emphasize that, unlike other binary operators such as `+`, this one is not commutative.  A snippet like "42 contains ns" would mean something else entirely, and doesn't even compile.

A DSL with ∈

Klingon (Tlingan) is an "object-verb-subject" language.  Translating word-by-word from such a language, "Her loves He", or more properly, "She is-loved-by him" again tells us about his feelings, but not hers.  Sometimes when writing code, it would be easier on the reader to shuffle the order of our operands.

  println(42 `∈` ns)

This of course does not compile because there is no such `∈` method of integers. However, when the gain in readability is worth the effort, Scala offers a way to write such expressive code.

  class MyElement[X](x :X) {
    def `∈`(xs :Set[X]) = xs contains x
  }
  implicit toMyElement[X](x :X) = new MyElement(x)

This approach contrasts a bit with monkey patching found in other languages.  On one hand, the Scala approach tends to be a bit more verbose, since a new class is defined.  On the other hand, Scala allows careful control over the modification's scope.  Instead of globally altering the integer type as monkey patching would do, Scala affects the code only where the implicit function is imported.

No comments: