Interactive development with Io: how to reload prototypes
The major feature of a dynamic language is interactivity. With Smalltalk you may run the program and inspect/change it at runtime. This implies some GUI for VM with built-in crappy text editor: you don’t edit files, you edit objects now.
This does not sound very comfortable for many reasons. First, you would always want to have a “canonical” state of your application which is not affected by runtime mutations: that is, plain text files stored under some version control. Next, you would like to use a different text editor or GUI and it is much simpler to achieve when you operate with plain files instead of fancy VM/language-specific API.
How do we combine interactivity of Smalltalk with text file editing? Let’s take the puriest OO language ever designed: Io.
1. Each file contains an expression.
2. The only way to load the file is to evaluate it in context of some object: object doFile("file.io"). The return value would be a result of the expression in the file.
3. We may have a convention that some files return a prototype object: the object which is used as a prototype for other objects created in runtime.
4. To load “prototype object” we use a special loader object which would track the file-to-object mapping: Article := Loader load("article.io")
5. Loader monitors the filesystem and when some file is changed, it loads it into another object and replaces the prototype with that object: Article become(load("article.io"))
6. At that point, all articles in the system suddenly have another version of Article proto.
You have to follow some safety rules. For instance, proto’s descendants should not modify the proto and rely on such modifications.
Of course, this method still does not allow you to change/inspect breakpoint message somewhere and use a debugger after the proto is reloaded and VM stepped on that message. Or wire some Smalltalk-like GUI to your app.
Simple proto-based reloading helps development a lot and in contrast to class loading methods with full app reload, works faster and for full range of source code including all libraries. Rails dependency system does not reload gems, but does a pretty good job with constant reloading. All ruby/rails issues with global data applied.
