miércoles, marzo 06, 2013

var self=this is not lame!

A few weeks ago I came across this article: http://ngauthier.com/2012/04/var-self-equals-lame.html and then I thought: "OK, let's follow this stranger's advice, I don't want to be lame!".

But what was really lame was to change my coding style just because other person said so. After thinking a little bit about it and writing some code; I found that the reasons given in the aforementioned article weren't very good...
  • Intent. self is totally unambiguous, and when you see a self it's very clear that it refers to a lexically scoped variable rather than a variable that might change at runtime.
  • Self-completeness. Why is 'leaning on a well tested library' good, when you could be using a core language feature instead?
  • Brevity. Oh, a one liner. SLOC's is the most simplistic (and usually wrong) metric for code complexity. Let's take another approach and count levels of nested parens and braces instead! I prefer reading two lines containing simple statements over a complex expression almost every time, because our brain handles poorly deep nesting.
  • Dangling code. I have to agree in that, but that's a minor problem and cleaning up unused variables is a task that we all have to face when refactoring code.
And there are some very good reasons to prefer self=this over bind(this):
  • Debugging. What do you see if you inspect a callback function variable that has been bound? This: function () { [native code] }. You don't get any information about which function is it, because all you see is a native code wrapper.
  • Nested callbacks. You have to bind two functions, even if you just use this in the inner callback.
  • "this" as as part of the callback API. Some callbacks will set a useful value for "this" (like the receiver of an event, or the current element in $.forEach); what if you want to use it?
So, emotional statements (like "don't do that, it is lame!") don't really belong to science or programming, as they bias your criteria. Avoid them.

viernes, febrero 15, 2013

Functional pagination (or CPS iterator pattern)

I know that I promised to write about Javascript... Not yet, but I'm almost there.

I’ve been thinking about implementing a purely functional pagination scheme for a product picker I’m working on… The motivation is that writing asynchronous code that manipulates mutable state is not to my taste.

Instead of having around the current offset counter, I’ve thought that each callback can receive (besides the data) two extra functions: one that returns the previous page and another that returns the next page (if any).

The widget is written in Javascript, which is great because you don’t have declare recursive function signatures, but you still need to use them without making any mistakes. To be sure of what I’m going to implement is not nonsense, I wrote a toy example in Scala before diving in:

import scala.collection.immutable.Range

object sandbox {

  trait PaginatedCallback[T] {
    def apply(results: List[T],
      prev: Option[PaginatedCallback[T] => Unit],
      next: Option[PaginatedCallback[T] => Unit])
  }

  def feed(callback: PaginatedCallback[Int]) = {
    def page(p: Int)(cb: PaginatedCallback[Int]): Unit = {
      val prev = if (p > 0) Some(page(p - 1)_) else None;
      val next = if (p < 10) Some(page(p + 1)_) else None;
      val results = Range(p * 10, (p + 1) * 10) toList;
      cb(results, prev, next)
    }
    page(0)(callback)
  }

  object printAll extends PaginatedCallback[Int] {
    def apply(results: List[Int],
          prev: Option[PaginatedCallback[Int] => Unit],
          next: Option[PaginatedCallback[Int] => Unit]) = {
      
      println(results);
      next match {
       case Some(cb) => cb(printAll)
       case None => println("finished")
      }
    }
  }
  
  feed(printAll)
  //> List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  //| List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
  //| List(20, 21, 22, 23, 24, 25, 26, 27, 28, 29)
  //| List(30, 31, 32, 33, 34, 35, 36, 37, 38, 39)
  //| List(40, 41, 42, 43, 44, 45, 46, 47, 48, 49)
  //| List(50, 51, 52, 53, 54, 55, 56, 57, 58, 59)
  //| List(60, 61, 62, 63, 64, 65, 66, 67, 68, 69)
  //| List(70, 71, 72, 73, 74, 75, 76, 77, 78, 79)
  //| List(80, 81, 82, 83, 84, 85, 86, 87, 88, 89)
  //| List(90, 91, 92, 93, 94, 95, 96, 97, 98, 99)
  //| List(100, 101, 102, 103, 104, 105, 106, 107, 108, 109)
  //| finished
}

I think it’s quite neat.

It took me a while to think, but once I wrote it, it just worked. I’m sure I wouldn’t have got it right in Javascript without a little trial and error.