portable perspectives

a blog about programming, life, universe and everything

Life polyglot (ruby,python)

dblack recently published a nice article about things rubyists need to think about when the long awaited 1.9 release finally appears (plus, a follow up).

Of course I'm happy of the changes, but I'd like to point out that as of today, 16 january 2009, we are still allowed to play with ruby in a way that is not going to be possible again in the future. For example, the following code implements a tiny game of life engine:

#! dunno how to [python,ruby].pick(random) in sh

ON = 1
OFF= 0
WIDTH          = 40    # WIDTH of "board"
HEIGHT         = 20    # HEIGHT of "board"


"""
# " 
def range(a,b) a...b end
def len(x) x.size end
def sum(x) x.inject{|a,b|a+b} end
def init() Array.new(HEIGHT){[0]*WIDTH} end
def spawn(board, left, top, shape)
"""
end=0
def gets(): raw_input()  
init=lambda :[[0 for x in range(WIDTH)] for x in range(HEIGHT)]
def spawn(board, left, top, shape):
  """
  "
  """
  # puts a new thingy on  board, at position (left, top),
  for y in range(0,len(shape)):
      for x in range(0, len(shape[0])):
          board[top + y][left + x] = shape[y][x]
      end
  end
end

t=init()
n=init()

#blinker
spawn(t,20,12,[[1,1,1]])
#glider
spawn(t,9,3,[[0,0,1],[1,0,1],[0,1,1]])
while 1:
  for y in range(1,HEIGHT-1):
    for x in range(1,WIDTH-1):
      c=sum([t[y-1][x-1],t[y-1][x],t[y-1][x+1],
            t[y][x-1],           t[y][x+1],
            t[y+1][x-1],t[y+1][x],t[y+1][x+1]])
      n[y][x]=OFF
      if c== 2:
        n[y][x]=t[y][x]
      end
      if c== 3:
        n[y][x]=ON
      end
    end
  end
  line = ""
  for y in range(0, HEIGHT):
      for x in range(0, WIDTH):
          if t[y][x]==0:
            line += '-'
          end
          if t[y][x]==1:
            line += 'O'
          end
      end
      line = line + "\n"
  end
  print line, "Life - press button for next generation\n"
  gets()
  t,n=n,t
end

Admittedly, the two effect are not 100% compatible, because python's print behaves differently from ruby's.

Why does it work?

Few reasons:

  • Ruby and python syntax are really similar
  • Even if nobody uses it, ruby allows a colon after if, while and for statements. Yet, it is forbidden after a function signature definition, so I have to conditionally define the function signature line
  • The top block is parsed differently from ruby and python: the latter sees a triple-quoted string, while ruby sees a sequence of normal strings, which are implicitly concatenated. In both cases the other language's code is inside a non used string
  • Some additional function definitions, some reordering (no else is possible) and everything works.

Well, works for some values of the word, since it executes correctly with ruby 1.8.7 and python 2.5, which are the two interpreters I have on my box, and it should work with any ruby 1.8.x and python 2.x.

But this code will not work with either python 3 or ruby 1.9. Well, just enjoy this tiny spot in time when we still were allowed to have multilingual code :)

AddThis Social Bookmark Button

Sorry, comments are closed for this article.