OOPSLA 2004 was great! It's the first time I've been back since 1996 (I presented a paper there). I'll write up my notes over the next few weeks as and when I get some time - I'll just be writing the delta between my experience and those of my colleagues: Martin Fowler, Steve Freeman, Nat Pryce and maybe others (sorry if I've left you out!).
Just a short addition to part 2 - I was writing some code the other day and came across another closure related problem with Python. I wanted to create some buttons, with event callbacks, dynamically; something like this:
class Foo:
def __init__(self):
self.callbacks = [lambda event: self.callback(name) for name in ['bob','bill','jim']]
def callback(self, name):
print name
def run(self):
for callback in self.callbacks:
callback("some event")
Now, what do you suppose happens when you run "Foo().run()"?
You get:
jim
jim
jim
This is because there is only one "name" variable (so Nat Pryce tells me). A simple solution is to do:
class Foo:
def __init__(self):
self.callbacks = [self.makeCallback(name) for name in ['bob','bill','jim']]
def makeCallback(self, name):
return lambda event: self.callback(name)
def callback(self, name):
print name
def run(self):
for callback in self.callbacks:
callback("some event")
I'm sure there are many other solutions too. For the curious, in Ruby the equivalent code would be:
class Foo
def initialize()
@callbacks = ['bob','bill','jim'].map {|name| Proc.new {|event| callback(name)}}
end
def callback(name)
print name
end
def run()
@callbacks.each { |callback| callback.call("some event") }
end
end
Foo.new.run()
which works just fine. However, I still chose Python over Ruby for pragmatic reasons (a bit ironic I know) - the libraries, tools and support are all superior.