Monday, February 17, 2014

Plain text screencast

“How do you install a foobar-quux?”, you hear it from the other side of the desk. “It’s easier to do than to explain”, you respond grabbing your keyboard. A few lines in the terminal and it’s done. You hesitate for a moment to write a neat script of what you’ve just done. But it’s not that easy, because… And it’s not worth it once you’re done. Until you hear the same question again in a week, “How did you install that foobar thing? It looked so easy, but I forgot.”
If you had a really lightweight screencast tool at hand which does nothing fancy, no screen resolution and frame rate settings. Just record what I do in the terminal.
The funny thing is this simple tool exists. It’s pretty old, actually, its first version was released in 2000. The original one is called ttyrec. It has quite some spinoffs. You can even upload it to the web and replay in the browser. I found more sites offering this service
My favorite one is Shelr.tv where you can change the replay speed.

Saturday, February 1, 2014

Rules to write functional Scala code and stay sane

Use only cases classes from the OOP world

Well, with some exceptions that will follow soon. But the baseline is: no regular classes, no inheritance. A case class can be considered an abstract data type, so it can serve as a container. Another use case for them can be seen as a little weird form of currying.

val people = List("Bob", "Mary")

// functional
def join(separator: String, list: List[String]): String = {
  list mkString separator
}

def joiner(separator: String) = {
  (list: List) => join(separator, list)
}

joiner(",")(people)

// with a case class
case class Joiner(separator: String) {
  def join(list: List[String]) = {
    list mkString separator
  }
}

Joiner(",") join people

Use traits only to simulate union types

There are cases when an instance can be one of two types, for example a tree node can be either a branch, or a leaf node. If we follow the above rule of using only case classes, we’ll be in trouble. This is where we can use a trait shared by some case classes.

trait TreeNode {}

case class Leaf(value: String) extends TreeNode {}

case class Branch(left: TreeNode, right: TreeNode) extends TreeNode {}
It’s OK to add methods to the trait if they would be shared by the case classes. (It would be difficult to use this tree example, because that would lead us to the field of recursive data types.)
trait NDArray {
  def rank: Int
  def isScalar = {
    rank == 0
  }
}

case class Scalar(value: Double) extends NDArray {
  def rank: Int = 0
}

case class Matrix(elems: List[Any]) extends NDArray {
  def rank: Int = {
    elems.headOption match {
      case Some(x: NDArray) => 1 + x.rank
      case None => 1
      case Some(_) => 1
    }
  }
}

Matrix(List(4)).rank // => 1
Matrix(List(Matrix(List(5)))).rank // => 2

Scalar(5).isScalar // => true
Matrix(List(4)).isScalar // => false

Avoid class level values

It’s a sign that you are about to add an unwanted dependency which will be difficult to inject/mock later. A typical usage to avoid is reading configuration values in the middle of some method.

case class BadGreeting(firstName: String, lastName: String) {
  val person = Person(firstName, lastName)
  val location = Configurator getConfigValue "greeting.location"

  def greetWith(greeting: String) = {
    greeting + ", " + person.fullName + " in " + location
  }
}

// That should be refactored to this class
case class GoodGreeting(person: Person, location: String) {
  def greetWith(greeting: String) = {
    greeting + ", " + person.fullName + " in " + location
  } 
}

Pass an argument object instead of too many arguments

The rules so far prefer explicit to implicit. It may lead to a loooong list of arguments, though. The cure for this is to create a case class for those arguments. It’s a matter of personal taste how many arguments you consider too many. I would say, don’t have more than three.