The image is the blessing and the curse of Smalltalk. It’s beneficial in that all the code for the whole system is there, and you can see it and potentially fix it from any debug window that you happen to open up. And there’s a huge amount of great stuff in there. The image is also what permits you to suspend and resume the computation, which enables some pretty magical functionality—like saving and restoring stack traces for debugging later or on other images than where they originated.
My biggest problem with having the code in the image is something that I haven’t seen talked about very much. Basically, the documentation for Smalltalk tends to suck. The tendency is to behave as though the code is all self-documenting because you can explore it in realtime in the image, but that doesn’t help you identify the code that is salient, or figure out what usages are good style and which are not. Narrative documentation for this kind of thing is really helpful.
My third problem with Pharo is basically that all my machines are high-DPI and they just don’t seem to be getting around to supporting that. I’m not going to write code through a blurry pixelated window, and I lack the knowledge to fix it. The Smalltalk world is sufficiently small that everyone is either OK with the status quo or perhaps unable to make the changes, but either way it’s a bit of a deal-breaker for me.
I spent a little time last year exploring Glamorous Toolkit though and I think it’s probably one of the best ways to get started with Smalltalk now. I greatly prefer it to Pharo—but unfortunately don’t have much call for using it myself.
I think there are better choices than Smalltalk for almost every task out there, but building something more than tiny in it is a worthwhile endeavor as a learning exercise. I was fortunate to have nearly a whole semester in Smalltalk during undergrad in the mid-2000s. Smalltalk absolutely informed the way that I structure my code and influences my decisions for what I like about languages (esp. named parameters). I’d like to think that I was a decent programmer for my highschooler-level experience before Smalltalk, but learning it (along with Scheme, for that FP/OOP balance) absolutely made me a better programmer.
I think the single-image is the biggest thing holding Smalltalk and co back. Hear me out – I don’t think sticking everything in text files and using that as the glue for everything like we do now is the answer either. I think there should be multiple images, and the communication protocols between them should be well-documented. There’s no reason for the running application and the (source + tools) to live in the same image or vm. Nor the current developer’s instance of the source and tooling. We should be able to pause and snapshot a running program for later debugging without that VM needing the developer tools to be in-process. Deployment would turn into “pause, disconnect the dev image, zip” rather than “painstakingly prune parts we think we don’t need at runtime without blowing up the tools we’re using to do this process”.
This would allow the images to be different, and support different operations. We do want a forever history of the source code and project-specific tooling, we probably don’t want that for every running instance of our software. We might want the code running within the live application image to be using a different compilation strategy, and we might want the option to jump into an application image from 6 months ago using the newest set of dev tools that we’ve been working on for the last 6 months. Or you’re like me and can’t stand Morphic and its descendants, but would still like to be able to add/replace methods and inspect data with all the powers you expect from Smalltalk.
There’s no need to give up the dynamism of a running smalltalk system, but unless you need it for business logic purposes, a running application VM should be worried about what is rather than what was, and this probably opens up a lot of new avenues where the different VM aspects might optimise for different use cases.
I think you’re right but also you risk losing out on a great strength- arguably the great strength- that this is a fully reprogrammable user interface. It’s much easier to see how you would incorporate something like the user’s choice of contextual help app that works across applications in something like a smalltalk environment.
This is similar to what we were trying to build with Étoilé. We had a persistence framework called CoreObject that provided a data model with diffing and merging, which we could use for things like unlimited persistent branching undo and remote collaboration. We built some GUI abstractions where the view hierarchy both exposed and consumed the CoreObject data model and so we could bind models to views but could also bind views to views if you wanted to inspect the view hierarchy and could persist the views in the same way that you’d persist the object. With Pragmatic Smalltalk I wanted to encode the AST in the same object model but still use existing native libraries.
One thing I really like about Smalltalk is the ability to save and restore the state of the VM at any time at any place. I really miss this in notebook environments like Jupyter as it is impossible to move my computation from one browser window to another.
Silly idea: use a Jupyter notebook with a Common Lisp kernel and save&restore the Lisp image?? (https://github.com/yitzchak/common-lisp-jupyter)
So, I’ve never tried using Pharo or Smalltalk in anger. But, I have had a thought bubbling in my mind ever since I heard about it: how do you collaborate with other people? Is there a way to diff two virtual machines, and patch them together? Could you even follow the “git flow” model?
Because it’s all one image all libraries are basically patches. Squeak (and I assume pharo) has its own version control system called Monticello.
AIUI, this is one of the raisons d’être of the Newspeak language. It takes a lot of its design influences from Smalltalk and Self (a later language in the same tradition), but it can serialise its code and objects out to text files, so that they can be saved in, for instance, a version-control system.
The abilities to dump and restore a running image, and to easily change everything at runtime, are the two biggest things I miss about Common Lisp. It feels barbaric now when I have to restart a JVM to pick up classpath changes, or when I have to wait a minute on startup for everything to get evaluated instead of just resuming a saved image instantly.
Besides demonstrating how much of the Smalltalk language can fit in a small space, is it supposed to be immediately clear what the “postcard” example actually does when executed?