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 :)

See all comments

Rails vs Django: a non biased yet useless comparison

Lately I've been making my hands a little bit dirty with django, and since I already did a little bit of Rails I think I'm entitled to do a small comparison. No, this is a lie. I'm entitled to do that because I have a blog and that's it.

The non biased assertion is due to the fact that I like both frameworks and I do love both languages, the useless one is well, because you will still have to evaluate the things by yourself , cause I am not an expert at either and I think that my few readers are smart enough to understand that choosing an infrastructure requires more work than reading a random blog entry.

Both frameworks use the new classic MVC pattern (even if in django's lingo it's called MTV you will notice that it is 99.9% the same), and both framework provide some othe features, so I'll just split the comparison by these concepts.

* Model * The model layer in django and rails is basically built out of classes that map to DB tables, but the things are slightly different.

The model in rails is comprised of two things: an SQL definition and a Ruby definition. Yes I know about Dr Nic's magic models. You can also create the database in pure ruby by using the wonderful migrations' system that rails provides, but the model is still built out of the pair DB structure + Ruby code. AFAIK django doesn't have yet something on the level of Rails migrations, that allows you to programmatically move back and forth in time easily.

Django uses a single definition in python with more metadata, and provides some useful python datatypes that are mapped transparently on the DBMS, so that a Post class can have a SlugField, while a Comment can have EmailField and IPAddressField. Yet, you can still go down to the SQL level if you want.

It seem to me that the support for validation is quite similar under the surface for both frameworks: you can validate single fields ot whole objects at different times and stack different validators.

One big flaw in current django's models is that they don't allow inheritance, and so if you have a lot of models that differ just slightly you can't save work using this approach. Rails' ActiveRecord gets a big plus for this, but this should be solved soon in django.

* "the thing that does *which" ** Rails calls the module that chooses which data to show the Controller. For some reason Django calls it the View whereas the Controller is the underlying support software.

Rails which is made of two elements: Controller objects and actions. A request for a page is processed so that it instantiates a Controller object and setups variables appropriately, then the action method is called. At the class level you can define behaviour shared between the various action with a nice syntax, but I don't particularly love the :except and :only things.

In django an action is just a function which takes a fixed argument, the request, and an optional set of named arguments. I love the way named arguments work in python and I think that this approach provides much more readability, but to have that in ruby we will have to wait for ruby 2.0 (or use evil.rb which doesn't feel enterprisey).

The only thing I dislike in django's view is that you have to explicitly point out to a template file when rendering a view, whereas rails' convention over configuration in this case relieves the user of a repetitive and non-interesting operation.

I also think that not having the class Foo < Controller boilerplate is better, but the bad news is that django doesn't do magic requiring of modules and you have to do it yourself, so everything balance out.

Both systems allow caching but (for what I understood) Django mostly uses time-based cache invalidation, while rails provides only an event-based expiring behaviour.

Anyway there are plugins for rails that allow time based invalidation, and I believe that it should be possible to expire something in an event-based fashion in django too, cause the underlying mechanics are the same (CACHE.set(key,val), CACHE.get(key) and CACHE.del(key)).

It seems that django doesn't provide the fine-grained caching control that rails has, allowing just a whole-page caching or forcing the user to resort to the low level cache api, which I think is a bad thing.

Finally, django uses exceptions to handle error codes, which I believe is a far better solution than rails :status=>code, because it allows breaking out of an action from an utility method. This allows, the refactoring control in utility methods, having shortcuts such as get_object_or_404(Class,key=val), which simplify the writing of views.

* "the thing that does _how_" * The actual showing of data is usually done in both frameworks through templates, which rails call Views. Django uses an interestint template language while rails uses ruby embedded in XHTML by deafult, but different templating engines can be used as plugins very easily.

Both allow the composition of smaller units to enhance reuse and ease of maintenance and it I believe that apart from personal preferences there are not big differences in this area.

* Other things * I think that the main differences in rails and django can be appreciated going away from the basic elements and looking at the rest of the platform, where the frameworks differ greatly.

First, django provides internationalization as a builtin concept while in django you're forced to use external libraries such as Globalize. Sadly, I am convinced that this is such an important feature that it must be builtin and it is an error not to have it, because to do it right the framework must be engineered around it. It must be also noticed that python's support for unicode (and other text encodings) in general is far more advanced than ruby's, which basically just kind-of-supports utf-8 (wait for ruby2, again).

Second, django's automatic generation of an administration facility, complete with authorization support and a bunch of space for customization is amazing. Again, there are modules for rails that provide this kind of behaviour, but having such a feature builtin makes it a foundation and a reference against which every programmer can code, which makes coee sharing easier.

In general django has builtin support for a lot of functionalities that are common in modern web apps, not only admin and auth, but also sitemaps, syndication, comments and much more.

Rails takes a minimalistic approach on this and pushes all this stuff in plugins. The rails community is producing plugins at an incredible rate, and even if not all of them are compatible and high quality code there is a lot of choice.

In the old days rails' plugins used to have some issues and this was the reason for the existence of things like rails engines but as of 1.2 this problems are not there anymore, Django allows code sharing through the integration of different apps which is what the admin above mentioned features are, and each of this add-on can contain something as easy as a textilize() function to a whole application such as a wiki or a blog.

There are not so much django apps as there are rails plugins, and I believe that this depends on 3 factors

  • smaller community
  • slightly harder sharing (in rails you just user script/plugin install and you're done)
  • less duplication The latter is hardly dependent on django coming with more batteries included, so for example you don't need a plugin for creating slugs because there is a lready a slugify() function.

* Conclusion * I wish rails had more batteries included, and that ruby was a little bit more like python (i.e. modules, named args, function decorator syntax). And I wish django used more conventions/less typing, and python was more like ruby (blocks, functions call without parenthesis, implicit self). but I still like both, pick your choice or even better try both. This at least will make you ready to write your own framework ;)

See all comments

AddThis Social Bookmark Button