Archive for the 'ruby' Category

The Tempting Abstractions

I’ve been meaning to figure out OSX development for a few years now. I’ve halfheartedly gone through the currency converter tutorial a few times, fooled around in XCode with various sample projects, worked through some of the NeHe OpenGL lessons that were ported to Mac, and even bought and went through the first edition of Aaron Hillgass’s book 3 or 4 years ago. What got me going again recently was an interest in combining native accelerated graphics with functional language extensibility. I was in part inspired by the ideas of the scheme-based fluxus. I reread the docs for PyObjC and RubyCocoa, and both seem like a lead. Then a few days ago I found Will Thimbleby’s concise tutorial and example project for using Javascript to script a Cocoa view. This is nice because the Javascipt engine is exactly the one used in Safari, based on KDE’s KJS engine. Even nicer is that his code is short and straightforward. In the end I will probably go back to figuring out Ruby and RubyCocoa, but this tutorial got me moving in this world again.

The biggest stumbling block in my Cocoa experience has been Interface Builder. I know it is supposed to be easy and elegant. But I’ve been suspicious, and consequently hesitant to really get into it. Along with other Apple systems like WebObjects and Quartz Composer, it requires aquisition of knowledge that is essentially non-transferable. Learning how to visually connect these specific little icons, widgets and outlets just isn’t going to help me in any other system. It is abstracted to the point of simulation, and learning the rules of the system involves little knowledge of the inner workings. It reminds me of the tension Sherry Turkle noted in the introduction to the new edition of The Second Self:

The aesthetic of transparency (common to the Logo movement and the early generations of personal computer hobbyists) carried with it a political aesthetic that was tied both to authorship and to knowing how things worked on a level of considerable detail. There is a kind of understanding that is not communicated by playing off-the-shelf simulations (p13).

Turkle is concerned that the increasing opacity in modern software and systems is leading to a new type of illiteracy within the emerging generation:

…as I meet professional in all of these fields who move easily within their computational systems and yet feel constrained by them, trapped by their systems’ unseen and unknown assumptions, I feel continued concern. Are the new generation of simulation consumers reminiscent of people who can pronounce the words in a book but don’t understand what they mean? (p14).

Yet I’m giving in. After investing only a few days I’m realizing how Interface Builder takes care of many parts of the application that I don’t ever want to handle myself. The abstraction is easier, simpler, and it saves me time, leaving room in my brain for other problems and puzzles. Turkle’s concerns are understandable, and to some extend I share them, yet I wonder whether it is in part nostalgia for an aethetic that is only interesting now that it is so obviously impossible (in a recent talk my colleague and friend Jeevan elaborated on the connection between simplicity and nostalgia for a simple past).

Maybe it is this tension between opaque abstraction versus transparent details that makes for good design. Which details do we choose to hide by assuming defaults? Which details do we conflate versus keep separate? Which details to we expose? As the abstraction increases, the gap between the two increases as well. Finding the balance is harder, yet also much more important.

Pascal’s Triangle in Ruby

My solution to the Pascal’s Triangle quiz this week:

#!/usr/bin/env ruby

def center_str s, len
  n = (len - s.length) / 2.0
  ' '*(n.floor) + s + ' '*(n.ceil)
end

n = ARGV[0].to_i
rows = [[1]]
for i in 1..(n-1)
  k = -1; r = rows[i-1] + [0]
  rows << r.map{ |x| j = k; k+=1; x + r[j] }
end
m = rows.last[n/2].to_s.length * 2
n = n * m
rows.each do |r|
  puts center_str(r.collect{|x| center_str(x.to_s, m)}.join, n)
end

Sample output:

                             1
                          1     1
                       1     2     1
                    1     3     3     1
                 1     4     6     4     1
              1     5     10    10    5     1
           1     6     15    20    15    6     1
        1     7     21    35    35    21    7     1
     1     8     28    56    70    56    28    8     1
  1     9     36    84   126   126    84    36    9     1