Seven Languages, Seven Weeks – Io

April 18, 2010

I’ve fallen behind, but not given up, on my seven week tour of different languages as I read Bruce Tate’s Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages. The second language in the tour is Io, a prototype-based language created by Steve Dekorte. Io is not mainstream, and perhaps not yet fully production ready, but it is interesting. In fact, part of my delay has been in digesting the very different paradigm that Io presents.

In a language like Io there are no classes – to create an instance, you clone something – either Object or something else that has ultimately been created by cloning Object or something else that has been created by cloning Object or something else… well, you get the idea. And everything about an object can be overridden, since those attributes are “slots” that can be arbitrarily assigned.

In Io everything is handled as messages passed to objects, and the way that any object handles any message (a slot, again) can be overridden. So in Io, ‘hello world’ becomes:

“Hello, world” print

That is, send the print message to the “Hello, world” object. And what’s in the print slot can be redefined. Once you get in the habit of looking at things that way a lot of options open up. Add to that some pretty slick concurrency handling and Io starts to look pretty intriguing.

I can’t describe Io in the small space of a blog post, so I’m not going to try. And in fact that would be exactly my criticism of Seven Languages. For such a different (from the procedural/OO norm) language, the text gets the reader in to deep water very fast. The thinness of explanation in the text quickly lead me to the web, which is sort of what the author intended. The problem is that looking at Io material on the web quickly became more absorbing than the text (what’s this? Python bindings for Io?) and it was only belatedly that I came back and played with the books’ examples.

And since I carped about it in an earlier post, I have to mention that I found it a little irritating that the author had to describe overriding an object’s forward method (the mechanism for searching prototypes to find a method) as being equivalent to Ruby’s method_missing, which seems to be a bit of a stretch (and a bit Ruby-centric). Io isn’t Ruby, and while it can be made to do something equivalent, it simply doesn’t have the same features.

On the other hand, I found the choice of Io to be a good one, and completely in line with the intention of the book. I didn’t really have any feel for prototype-base languages before, and now I feel I do.

One of the comments on my post about the Ruby chapter suggested that if I was upset about Ruby, Io would give me a heart attack. In fact, my heart rate ended up being quite low. I had quite a bit of fun playing around with Io and figuring out how to create a DSL to produce XML. I think the reason is Io’s consistency and simplicity. EVERYTHING is objects with slots being passed messages, and that’s pretty much it. Once you accept that, Io behaves as you would expect.

While I’m not entirely sure that Io is ready for production use, I can definitely see implementing a DSL in it, and I may well be be back to experiment more.


Python and recovering Firefox sessions

April 11, 2010

First let me confess, I am a tab-aholic…

I tend to have several Firefox windows open at once, with several tabs in each. And I leave them open for… well… weeks. And usually that’s fine – it restores everything if I have to reboot or restart Firefox, and all is well. Except when it doesn’t.

Sometimes, for whatever reason, the sessions aren’t restored, and all of those tabs, as in “hey, I wasn’t quite done with that!”, are lost.

When this happened to me last night, I took a look in my Firefox profile directory and discovered something about the way Firefox stores it’s sessions. I’m sure it’s well-known to many, but it was news to me.

When I looked at sessionstore.bak (the automatically created backup of sessionstore.js) I saw something like:

({"windows":[{"tabs":[{"entries":[{"url":"http://stoa.canterburyschool.org:9080
/stoa/courses/Faculty/TechnologyGuides/VoIPandSkypeinForeignLanguage
/document_edit_form","title":": VoIP and Skype in Foreign Language","ID":2528274837}...

Hmmmm… I know that’s Javascript, but it also looks a lot like a Python dictionary. Why not see if Python could eval() it to a dictionary? My first try failed on the unknown identifiers “true” and “false”, but after defining true and false as equal to Python’s True and False, it worked. Now I had a nested set of dictionaries containing all of my previous session’s info. Not bad.

[Edit: Not being a regular JSON user, and since the file extension was .js, not .json, I never considered that this might be JSON. It turns that it's not QUITE JSON and the Python JSON library won't decode it (without at least stripping off the leading and trailing parentheses). Check out this discussion for more info.]

From there it was easy to create some code that would grab the URL’s from an unrecoverable session and put them into an HTML page for easy access later.

Warning: this code uses eval() on arbitrary strings loaded from an arbitrary file, so it is not secureuse with great caution. If it wipes your hard drive, sells your house and absconds with the money, and kicks your dog on the way out, you have been warned.

In any case, below is my session recovery code, which I’ve already used a couple of times.


import sys
""" this code is released to the public domain and meant only for illustration. It is not
    warranted as being safe or suitable for any particular purpose at all.

    in particular, this program evaluates (and potentially executes) arbitrary code,
    so use with caution.
"""

def get_session(infilename, outfilename):
    true = True
    false = False
    sessionstring = open(infilename).read()
    session = eval(sessionstring)

    outfile = open(outfilename, "w")
    for window in session['windows']:
        outfile.write("---------------Window-----------------<p>\n")
        outfile.write("<ul>\n")
        for tab in window['tabs']:
          outfile.write( '<li><a href="%s" \="">%s</a> - %s</li> \n' %
                         (tab['entries'][0]['url'],tab['entries'][0]['url'],
                          tab['entries'][0]['title']))
        outfile.write("</ul>\n")
    outfile.close()

if __name__ == '__main__':
    infile = sys.argv[1]
    if len(sys.argv) == 3:
        outfile = sys.argv[2]
    else:
        outfile = "sessionsave.html"

    get_session(infile, outfile)

Seven Languages, Seven Weeks – Ruby

April 1, 2010

I just finished the first stop on my seven language tour. Ruby was in some ways an easy start, although not as easy as I would have thought. While Ruby is enough like Python to seem familiar, I was still surprised by some of the differences I found.

The author of the book, Bruce Tate, is a Rubyist as I understand it, and he was definitely pushing metaprogramming as one of Ruby’s cool features. And in that department (and in others) Ruby definitely has some cool tricks.

After some easy build-ups, including arrays and hashes (pretty much equivalent to lists and dictionaries in Python), a sort of slick implementation of a Roman numeral class, and using inject to cumulatively operate on all of the elements of an array, the final problem to be solved in Ruby is creating a module which creates a class to read a CSV file. The file is opened automatically when an object of the class is instantiated, assuming a filename derived from the class name. That is, if the class is ‘ActAsCsv’, it will open a file ‘actascsv.txt’.

The first line of the CSV file is assumed to be a header containing the names of the fields, and one is supposed to create a CsvRow class which supplies accessor methods corresponding to each field. So if the first line contains “one, two, three”, you should be able to access the third field of any row with ‘row.three’.

A few things in this exercise left me feeling uncomfortable. First of all, the automatic opening of a file based on the class name, struck me more a parlor trick to illustrate Ruby’s capabilities for introspection, than a practical strategy. While I can do the same thing in Python, I can’t think of a single instance, even in simple scripts, where I would be happy linking all instances of a class to a single file, or even constraining what file is opened. I try to write my classes to handle arbitrary file names instead. I may be making too much of this, but as a teacher I’ve come to really dislike teaching examples which make you say “huh?” right at the beginning.

I’ve always advocated to my programming students that they write programs in such a way that runtime errors are obvious. If an error matters, it should be as obvious as possible, so that you can find and fix it. so I was surprised and a little uneasy to discover that Ruby seems to be taking the opposite approach – if a field or method or array slot is missing, just return nil and carry on. That’s right, no index out of bounds exceptions… ever.

In fact, Ruby takes things one step further. Objects have a overridable method ‘method_missing’ which gets called whenever you try to access a method that the class doesn’t actually have. The default version raises a NoMethodError exception, but once you override it, the behavior is up to you. This is powerful – if you construct your method correctly you can do some interesting things, including dynamically supplying field accessors for rows in CSV file. OTOH, if you don’t construct it right, if you don’t remember to raise a NoMethodError for the truly unexpected values, you run the risk of masking important information.

In my solution, the contents of the row are a hash in the CsvRow, and the method_missing implementation of the accessors is really just syntactic sugar hiding a key, value hash lookup. Add to that the fact that Ruby returns a nil rather than raising an exception if a key isn’t found, and my code can’t tell the difference between an empty field and a missing one. I freely admit my solution may not be the “Ruby way”, but I would argue it’s at least plausible.

So while I’m glad I had the chance to play with a bit of Ruby, and I’m still liking the books approach, I end up with two issues, one regarding Ruby and the other with the example problem. The first is what I’ve just mentioned – I was guided into using Ruby in a way that I think conceals potential bugs, and Ruby was complicit in that.

The second issue is with the exercise. While I’ll certainly concede that Ruby has some syntactic flexibility that Python doesn’t, this problem doesn’t really present a convincing use case. I don’t intend to make my reading of this book into just a ‘so what, I can do that in Python’ response, but in this case it does seem to me that a Pythonic version takes care of the problem more efficiently. If I’m OK with using dictionary access rather than accessor methods – saying ‘row["one"]‘ rather than ‘row.one’ – this example is a non-problem in Python, thanks to the csv module in the standard library.

[Edit: Yes, I know that you can override __getattr__ in Python to provide the same functionality. See the comments for suggested versions. My point was that Ruby's method_missing approach was what made me uneasy. And it's more inviting - in Ruby you would override the method_missing method of a class derived from hash, and nothing else. In Python, I would argue, the surgery is a bit more serious.]


Follow

Get every new post delivered to your Inbox.

Join 131 other followers