Loose Articles

a blog by Josh Dzielak

picture of Josh

Hi, I'm Josh, an engineer and entrepreneur living in San Francisco. I write about code, companies, and ideas. I work at Keen IO.
Find me on twitter and github.

Jumping between JavaScript and Ruby Closures

These days I find myself constantly jumping between Ruby and Javascript when creating web applications. Some days I feel like Hiro Protagonist, with these languages as my twin katanas.

Except… that they’re obviously not twins. And when switching back and forth constantly it’s easy to forget the individual subtleties of features that these languages share in concept but not in implementation.

It’s not so much the syntax that trips me up, but rather the design aspect. I’ll sometimes come under a temporary cognitive bias after working with one language – causing its patterns to surreptitiously leak into the design of software in the other language.

After writing JavaScript for a few hours, I’m more likely to unwittingly solve a Ruby problem via a JavaScript-y technique – perhaps by [over]using closures. In an app that’s written in a mostly imperative style, tossing in functional programming elements can be confusing.

As of now, I’ve made a special mental note to take a deep breath when switching and let the brain get properly back into context. For heading back to Ruby when working with closures I find reviewing this guide, Closures in Ruby, to be a helpful reminder of the available patterns.

Also, syntactically it’s not a bad idea to glance over Proc, lambda, and function:

#in ruby
p = Proc.new {|n| return n; }
other_p(p)    #ok
p(1)          #ok
p.call(1)     #error! unexpected return    

p = Proc.new {|n| n }
p.call(1)     #ok, returns 1

#this is ok too
def j(i)
  p = Proc.new {|n| return n; }
  p.call(i)
end
j(1)          #ok - returns 1

#and ok with lambda
p = lambda {|n| return n; }
p(1)          #ok, lambda lets caller stay in control

That’s because of this whole business. Correspondingly in JavaScript,

//in javascript
var f = function(n) { return n; }    
otherF(f)        //ok
f.call(1)        //ok
f(1)             //ok