Interesting talk. Smalltalk (like Lisp) has indeed a very simple (i.e. minimal) syntax. But that doesn't necessarily mean that it is also simple to write and read code, or to implement an efficient compiler. E.g. blocks - as great as they are - make inlining very difficult; it eventually took 30 years to implement a VM with decent performance (see http://software.rochus-keller.ch/are-we-fast-yet_crystal_lua... for the results of https://github.com/rochus-keller/Som/ and https://github.com/rochus-keller/Smalltalk/ compared to Cog/OpenSmalltalk). Another language explicitly designed for simplicity is e.g. Oberon, which is statically typed and easier to implement with decent performance.
In my experience, at the end of the day, it's more the familiarity with a language that makes it seem "simple". And there is a trade-off between "simplicity" of the language and "simplicity" of the solution; if the language is too minimal, the solution quickly becomes confusing instead, and vice versa.
Self wasn't sufficiently fast? Craig Chambers's compiler [0] had to be careful around recursive inlining* but it's not that bad, and the compiler definitely came around in less than 30 years of Self or Smalltalk existing (even if you start counting from Smalltalk-72).
A sibling comment mentions that Smalltalk-80 played tricks with inlining some block methods such as ifTrue: and whileTrue: in the bytecode, but Self pulled nothing like that.
*Although maybe too careful - the important parts are that you don't inline forever, so some degree of recursive inlining is okay (and would help in the factorial example), and that you have a good reason to inline.
Self apparently is sufficiently different from Smalltalk-80 so that even today JS engines (which are descendants of the Self engine) are still significanly faster than Cog/OpenSmalltalk. Remember that also Python is known to be pretty resistant to performance improvements. So some languages/VMs apparently are more amenable than others. In my referenced report you can see that there is still nearly a factor two between Pharo (using OpenSmalltalk) and Node.js (using V8). But Pharo is at least faster than LuaJIT, which again is about factor 220 faster than a Smalltalk interpreter which does the caching and inlining described in the Bluebook. So Cog/OpenSmalltalk went a long way to finally be the fastest Smalltalk engine around. A comparison with Smalltalk 72 makes little sense because it was a completely different language and engine.
> Smalltalk-80 played tricks with inlining some block methods such as ifTrue: and whileTrue:
That was just because a convention on lexical level made it possible. Otherwise it's very difficult because a block is just an object and executing it is just a method call on this object via dynamic dispatch; it's not trivial to find out what to inline. If you're interested in the machinery behind the scenes, here are a couple of tools which facilitate an analysis: https://github.com/rochus-keller/Smalltalk.
> But that doesn't necessarily mean that it is also simple to write and read code
Right, having several friends in the smalltalk/Squeak scene I tried "obvious" things that required to know the patterns of, for example, Morphic framework [1]. I understand that if you include a good development wizard/assistant would significantly improve the learning curve.
Second chance pool. When a post is on there, it will may get its timestamp updated to the current time and will be tracked as if it was submitted at that time. All existing comments will get that same timestamp for a while. The fake timestamp helps to game the ranking so it goes to the front page for its second chance at discussion and votes. Eventually the real timestamp is restored.
Seeing an article about Smalltalk with Hernan presenting so up in HN is nice.
I worked with Hernan a while ago. We worked in a financial system with very cool things: an OO database, a workflow system that can work locally or remotely transparently, a good model for units and dates, tons of custom tools in the IDE (something that is only possible with Smalltalk IDEs) that allowed us to automate unit test generation, versioning, and database migrations. The last time I saw that level of productivity in any IDE was then.
However, Smalltalk is not perfect, and when I see these presentations, I cannot stop thinking that a more balanced discussion is needed.
The presentation shows how Smalltalk blocks are uniform with the if/then/while syntax. But that's only part of the history. To support blocks that way, the compiler optimizes those cases and inlines the block unless you do something else. So, while assigning the block to a variable looks the same, it's not executed similarly. That's the beauty of hiding the implementation details. But, sometimes, those details bite you. Most St programmers avoid creating custom "ifThen:else" messages because, in most VMs, that will break.
In other words, like any design decision, the simplicity of the "object message" syntax has trade-offs, too. The performance trade-off is fixed by having exceptional cases hidden from most programmers. The other trade-off is the need to always dispatch to a receiver. Compared to Lisp or other functional languages, the need for a receiver dramatically impacts how you design and structure your program. Many things that you can resolve with a polymorphic function need to spread across classes in St. And that introduces the problem of sharing the implementation: class hierarchies, traits, or composition. Resolving those problems with a simple function is refreshing and falls under the statement at the beginning of the talk: the programming language affects how you think about the problem. When I look at the code I wrote back then in Smalltalk or Java, I cannot stop thinking about how the restriction of using classes and methods adds unnecessary complexity.
I'm a little confused by the receiver thing. Is the idea that each object has a dictionary mapping function names to code and sending a message to an object means execute whatever was found in that dictionary?
So the example of { a < 3 } while involves evaluating a block, getting a boolean, then calling the while method on that boolean?
That would seem to have a bad time with things like compare. Neither argument is special, you end up implementing a lot of compare-with methods. I.e. the expression problem. Is that understanding broadly correct?
Pretty much although it doesn't end up being quite as bad as it sounds.
For example, your code wants to compare a string with some other object, if the other object understands 'string' then the built in method for comparing two strings can work. Otherwise you get a #doesNotUnderstand exception.
Making arbitrary comparisons is a bit silly though, so in practice it doesn't happen very often.
> Is the idea that each object has a dictionary mapping function names to code and sending a message to an object means execute whatever was found in that dictionary?
Isn't that how Python, Ruby, JS etc. work under the hood anyway? And yes it's quite predictably a drag on performance.
If one needs to run Squeak in a very minimum VM . Is it possible? Any help with that?
I tried to make vm in Squeak turning off graphics/sound and compiled vm but it just didn’t work when I was trying to run it.
Is there a relatively simple way to remove all fancy objects and keep only bare minimum that would at least run it so I can learn it further?
It has to be VM that gives repl through terminal and ability to modify image further, vm need to run without breaking if graphics/sound not available when even linux drivers aren’t available, on pi zero w let’s say.
With my current limitations I cannot dive into learning the language deeply in any other different setup.
Is it possible? I am sure someone have already done that somewhere. I am really trying to avoid dealing with c++ but the way vm is done it seems that instead of learning Squeak I have to dive into all the ‘beauty’ of compiling c with cmake instead.
Story time. When I was a young developer in a database company, my cubicle was next to a section where a team sat. The team consisted 30 to 40 people working on a secret project. Whenever I asked them what they were working on, they said it’s a secret next gen technology. They spoke in secret code and big terms. The only thing I knew was they were using Smalltalk as the language as they weren’t shy in speaking beamingly about it. They work on these powerful workstations with large monitors, a luxury at the time, as the Smalltalk dev studio required them. I thought these were god developers, working with advanced technologies in a covet skunk project.
The project went on for couple years. Nobody knew what they were doing, not their goals, their product plan, their features, nor their designs. The only thing we knew was they were using Smalltalk.
The high-up forced them to give a demo eventually. The talk was good, on Smalltalk, on OO, and on the landscape of the technologies. When the demo started, it showed a half finished login dialog box but nothing else. They said something about unable to package the code and do a release. Understandably software releases were a big bang process back then. But what about prior releases? Nothing. They didn’t have any finished builds. The talk continued.
Smalltalk was always good for rapidly developing GUIs, so whatever the reason was that they only had a half-finished login box to demo, it probably wasn’t Smalltalk’s fault.
Rapid development tools can’t help you if you don’t know what to build.
My guess is the secrecy of the project was the main contributing factor to its failure. There were no vetting on the products, feature, design, development process, technologies, language choice, etc. Too many people read Skunk Works and thought they were Lockheed Martin.
The language choice probably contributed somewhat. Smalltalk used to have problems with source version control and configuration management. It's difficult for multiple people to work on the same codebase. Merging change was difficult as the individual development environments were modified. The rapid prototyping was probably a false lead as it lured decision makers into thinking lower development cost.
By and large when the only thing about the project you can talk about is the language used, it is probably doomed to fail.
I have dabbled with Pharo smalltalk a bit and got a similar feeling.
The core "thing" (pharo it self) works well enough, other stuff you'll likely have to write on your own (batteries are not included).
Also, multi-threading seems to be non-existant? No FOSS implementation does that AFAIK (proprietary implementations are irrelevant).
I see the nicety of the language, but I'm not convinced (at all) by the implementation. Oh and Pharo seems to be the most advanced implementation of Smalltalk?
It really doesn't look practical at all.
But then again, the video starts and the guy is kinda deriding some Java or C++ code but then you move forward (eg: 8:31) and the speaker has a whole display filled with unrelated things and has to write code in a small text area, viewing like 4 lines at the time? Thanks, i'll pass...
Generally if your method in Smalltalk is 4 lines you're doing something wrong. Most good Smalltalk ends up being only 1 or 2 lines at the most, which is why the "coding" window always looked weird and small compared to contemporary languages.
You know what's funny. In one of the startups, we did bring in a TV crew to shoot commercials on us working. The commercials were aired before the product was half way ready. In one of the product demos in a trade show, the CEO was clicking on the software and I was sitting behind the stage inserting rows into the database on cue to create the illusion that the product was working since it was way before alpha.
Worth watching even if you skip to the last couple of minutes, where he tests a Game of Life scenario in a way that is not comparable to anything I've seen done with any other programming language.
This power that Smalltalk systems have where the code runs in a GUI that is also the editor/debugger/etc has deeply fascinated me recently.
At the same time it makes me kind of sad, because it feels like we're all stuck writing code with a hand tied to our back. Almost makes me think that there's a happy alternative coding universe where the Smalltalk way is the default way, and a couple of weirdos are using separate IDEs/editors and restart their program on every change, or think they're smart if they're running something as primitive as a REPL.
The reason why I'm not just diving in and never looking back is that it seems like such a big investment, and that I'm so comfy with my (very) extended Neovim setup. And I'd like to be able to create applications that run without shipping the entire Smalltalk VM. And I'd like to actually understand a tool that I'd have to dive into that deeply, and I think I'll never have the time to truly understand all of the VM, the classes, etc.
Maybe instead, I should just create my own language that contains its own code editor. Seems like almost the same time investment, but maybe more satisfying?
Sigh...
Anyway, here is some other related interesting material:
- Bret Victor - Inventing on Principle (Always funny to hear the crowd go nuts when he does the live game editing time thingy.)
- Pretty much any Alan Kay video.
- Dan Ingalls his "Lively Kernel", which seems to me like it's pretty much the same as a Smalltalk system, but where you code in JavaScript, and it runs in the browser.
> This power that Smalltalk systems have where the code runs in a GUI that is also the editor/debugger/etc has deeply fascinated me recently.
Have you tried emacs?
> And I'd like to actually understand a tool that I'd have to dive into that deeply, and I think I'll never have the time to truly understand all of the VM, the classes, etc.
I've recently tried to do that myself with Smalltalk via the Glamorous Toolkit[1] (a beautiful, modern Smalltalk environment based on Pharo). Because the programming environment itself comes with a Book teaching it, you can basically just read it as a normal digital book, but with the superpower that everything is editable and interactive: you can change the book itself, every code example is runnable and you can inspect the result objects right there, change it, modify the view for it... they say it's "moldable development" because you almost literally mold the environment as you write your code and learn about the platform.
> And I'd like to be able to create applications that run without shipping the entire Smalltalk VM.
That's why even though I really enjoyed SmallTalk, I can't really see it as anything more than a curiosity. I tried using it at least for my own occasional data exploration because it has good visualisation capabilities and super easy to use HTTP client/JSON parser etc., but the system is so heavy (1GB+ of RAM) that I couldn't justify keeping it open all the time like I do with emacs, on the offchance that I might need to use it for some small task.
Anyway, perhaps that's something you might be interested in.
Consider the case where you fundamentally modify the invariants of an object. All you existing instances might now be in some inconsistent state. One way to avoid this is to enforce some unity of code and state. If we instead of modifying all the existing instances just modify instances created from this point forwards, we don't risk messing with the invariants.
Well now we have a standard unix model. The executables are "classes" that get "instantiated" (exec'd) into "instances" or processes.
I was excited in Smalltalk around 1999, during my Master Thesis. The sad story is Java Hotspot had more technology than ParcplaceDigitalk(Cincom) and kept growing.
I love Smalltalk but Java won, even when it was closed sources.
Try Squeak (or Cuius): it is beautiful,but sadly it has little traction.
Java didn't win, you are still free to code in whatever language you are comfortable in. At least until the great big Jenga tower stack of modern-day dependencies and API's your language relies on eventually stop working, which is the real killer, not how good or bad your chosen language is.
Smalltalk technology acquired by Sun lives on Hotspot, while IBM's Smalltalk technology lives on Eclipse and J9, and Rogue Wave had one of the first collection frameworks.
It doesn't help when Smalltalk vendors were the first to jump into Java.
Small clarification: the Smalltalk technology absorbed by HotSpot was StrongTalk's static type-based optimization techniques combined with dynamic recompilation (what we now moniker as a JIT) originating from research done with Self (which was also part of Sun at the time).
Is it actively developed? Tried to use it once, but the class browser didn't work under Ubuntu or Debian. At least not in the version available at the repositories.
I remember clear as water to this day the feeling when I was a teenager doing C/C++ that it was with Smalltalk the first time I experienced the power of creating software that doesn't give you bad surprises for unknown reasons.
In my experience, at the end of the day, it's more the familiarity with a language that makes it seem "simple". And there is a trade-off between "simplicity" of the language and "simplicity" of the solution; if the language is too minimal, the solution quickly becomes confusing instead, and vice versa.
A sibling comment mentions that Smalltalk-80 played tricks with inlining some block methods such as ifTrue: and whileTrue: in the bytecode, but Self pulled nothing like that.
[0] http://www.wolczko.com/tmp/ChambersThesis.pdf#page=72
*Although maybe too careful - the important parts are that you don't inline forever, so some degree of recursive inlining is okay (and would help in the factorial example), and that you have a good reason to inline.
Self apparently is sufficiently different from Smalltalk-80 so that even today JS engines (which are descendants of the Self engine) are still significanly faster than Cog/OpenSmalltalk. Remember that also Python is known to be pretty resistant to performance improvements. So some languages/VMs apparently are more amenable than others. In my referenced report you can see that there is still nearly a factor two between Pharo (using OpenSmalltalk) and Node.js (using V8). But Pharo is at least faster than LuaJIT, which again is about factor 220 faster than a Smalltalk interpreter which does the caching and inlining described in the Bluebook. So Cog/OpenSmalltalk went a long way to finally be the fastest Smalltalk engine around. A comparison with Smalltalk 72 makes little sense because it was a completely different language and engine.
> Smalltalk-80 played tricks with inlining some block methods such as ifTrue: and whileTrue:
That was just because a convention on lexical level made it possible. Otherwise it's very difficult because a block is just an object and executing it is just a method call on this object via dynamic dispatch; it's not trivial to find out what to inline. If you're interested in the machinery behind the scenes, here are a couple of tools which facilitate an analysis: https://github.com/rochus-keller/Smalltalk.
Right, having several friends in the smalltalk/Squeak scene I tried "obvious" things that required to know the patterns of, for example, Morphic framework [1]. I understand that if you include a good development wizard/assistant would significantly improve the learning curve.
[1] https://wiki.squeak.org/squeak/morphic
https://news.ycombinator.com/pool
I worked with Hernan a while ago. We worked in a financial system with very cool things: an OO database, a workflow system that can work locally or remotely transparently, a good model for units and dates, tons of custom tools in the IDE (something that is only possible with Smalltalk IDEs) that allowed us to automate unit test generation, versioning, and database migrations. The last time I saw that level of productivity in any IDE was then.
However, Smalltalk is not perfect, and when I see these presentations, I cannot stop thinking that a more balanced discussion is needed.
The presentation shows how Smalltalk blocks are uniform with the if/then/while syntax. But that's only part of the history. To support blocks that way, the compiler optimizes those cases and inlines the block unless you do something else. So, while assigning the block to a variable looks the same, it's not executed similarly. That's the beauty of hiding the implementation details. But, sometimes, those details bite you. Most St programmers avoid creating custom "ifThen:else" messages because, in most VMs, that will break.
In other words, like any design decision, the simplicity of the "object message" syntax has trade-offs, too. The performance trade-off is fixed by having exceptional cases hidden from most programmers. The other trade-off is the need to always dispatch to a receiver. Compared to Lisp or other functional languages, the need for a receiver dramatically impacts how you design and structure your program. Many things that you can resolve with a polymorphic function need to spread across classes in St. And that introduces the problem of sharing the implementation: class hierarchies, traits, or composition. Resolving those problems with a simple function is refreshing and falls under the statement at the beginning of the talk: the programming language affects how you think about the problem. When I look at the code I wrote back then in Smalltalk or Java, I cannot stop thinking about how the restriction of using classes and methods adds unnecessary complexity.
So the example of { a < 3 } while involves evaluating a block, getting a boolean, then calling the while method on that boolean?
That would seem to have a bad time with things like compare. Neither argument is special, you end up implementing a lot of compare-with methods. I.e. the expression problem. Is that understanding broadly correct?
For example, your code wants to compare a string with some other object, if the other object understands 'string' then the built in method for comparing two strings can work. Otherwise you get a #doesNotUnderstand exception.
Making arbitrary comparisons is a bit silly though, so in practice it doesn't happen very often.
Isn't that how Python, Ruby, JS etc. work under the hood anyway? And yes it's quite predictably a drag on performance.
I tried to make vm in Squeak turning off graphics/sound and compiled vm but it just didn’t work when I was trying to run it.
Is there a relatively simple way to remove all fancy objects and keep only bare minimum that would at least run it so I can learn it further?
It has to be VM that gives repl through terminal and ability to modify image further, vm need to run without breaking if graphics/sound not available when even linux drivers aren’t available, on pi zero w let’s say.
With my current limitations I cannot dive into learning the language deeply in any other different setup.
Is it possible? I am sure someone have already done that somewhere. I am really trying to avoid dealing with c++ but the way vm is done it seems that instead of learning Squeak I have to dive into all the ‘beauty’ of compiling c with cmake instead.
The project went on for couple years. Nobody knew what they were doing, not their goals, their product plan, their features, nor their designs. The only thing we knew was they were using Smalltalk.
The high-up forced them to give a demo eventually. The talk was good, on Smalltalk, on OO, and on the landscape of the technologies. When the demo started, it showed a half finished login dialog box but nothing else. They said something about unable to package the code and do a release. Understandably software releases were a big bang process back then. But what about prior releases? Nothing. They didn’t have any finished builds. The talk continued.
The project got canceled couple months later.
Rapid development tools can’t help you if you don’t know what to build.
The language choice probably contributed somewhat. Smalltalk used to have problems with source version control and configuration management. It's difficult for multiple people to work on the same codebase. Merging change was difficult as the individual development environments were modified. The rapid prototyping was probably a false lead as it lured decision makers into thinking lower development cost.
By and large when the only thing about the project you can talk about is the language used, it is probably doomed to fail.
The core "thing" (pharo it self) works well enough, other stuff you'll likely have to write on your own (batteries are not included).
Also, multi-threading seems to be non-existant? No FOSS implementation does that AFAIK (proprietary implementations are irrelevant).
I see the nicety of the language, but I'm not convinced (at all) by the implementation. Oh and Pharo seems to be the most advanced implementation of Smalltalk?
It really doesn't look practical at all.
But then again, the video starts and the guy is kinda deriding some Java or C++ code but then you move forward (eg: 8:31) and the speaker has a whole display filled with unrelated things and has to write code in a small text area, viewing like 4 lines at the time? Thanks, i'll pass...
Smalltalk has been practical in past decades, that doesn't mean it's practical for you in this decade.
https://dl.acm.org/doi/pdf/10.1145/226239.226264
This power that Smalltalk systems have where the code runs in a GUI that is also the editor/debugger/etc has deeply fascinated me recently.
At the same time it makes me kind of sad, because it feels like we're all stuck writing code with a hand tied to our back. Almost makes me think that there's a happy alternative coding universe where the Smalltalk way is the default way, and a couple of weirdos are using separate IDEs/editors and restart their program on every change, or think they're smart if they're running something as primitive as a REPL.
The reason why I'm not just diving in and never looking back is that it seems like such a big investment, and that I'm so comfy with my (very) extended Neovim setup. And I'd like to be able to create applications that run without shipping the entire Smalltalk VM. And I'd like to actually understand a tool that I'd have to dive into that deeply, and I think I'll never have the time to truly understand all of the VM, the classes, etc.
Maybe instead, I should just create my own language that contains its own code editor. Seems like almost the same time investment, but maybe more satisfying?
Sigh...
Anyway, here is some other related interesting material:
- Bret Victor - Inventing on Principle (Always funny to hear the crowd go nuts when he does the live game editing time thingy.)
- Pretty much any Alan Kay video.
- Dan Ingalls his "Lively Kernel", which seems to me like it's pretty much the same as a Smalltalk system, but where you code in JavaScript, and it runs in the browser.
Have you tried emacs?
> And I'd like to actually understand a tool that I'd have to dive into that deeply, and I think I'll never have the time to truly understand all of the VM, the classes, etc.
I've recently tried to do that myself with Smalltalk via the Glamorous Toolkit[1] (a beautiful, modern Smalltalk environment based on Pharo). Because the programming environment itself comes with a Book teaching it, you can basically just read it as a normal digital book, but with the superpower that everything is editable and interactive: you can change the book itself, every code example is runnable and you can inspect the result objects right there, change it, modify the view for it... they say it's "moldable development" because you almost literally mold the environment as you write your code and learn about the platform.
> And I'd like to be able to create applications that run without shipping the entire Smalltalk VM.
That's why even though I really enjoyed SmallTalk, I can't really see it as anything more than a curiosity. I tried using it at least for my own occasional data exploration because it has good visualisation capabilities and super easy to use HTTP client/JSON parser etc., but the system is so heavy (1GB+ of RAM) that I couldn't justify keeping it open all the time like I do with emacs, on the offchance that I might need to use it for some small task.
Anyway, perhaps that's something you might be interested in.
[1] https://gtoolkit.com/
Here we go ...
Consider the case where you fundamentally modify the invariants of an object. All you existing instances might now be in some inconsistent state. One way to avoid this is to enforce some unity of code and state. If we instead of modifying all the existing instances just modify instances created from this point forwards, we don't risk messing with the invariants.
Well now we have a standard unix model. The executables are "classes" that get "instantiated" (exec'd) into "instances" or processes.
There's always a javascript vm... https://squeak.js.org/
Are you OK shipping the entire JVM?
It doesn't help when Smalltalk vendors were the first to jump into Java.
You’d get virtualization, multi threading, scalability, etc.
And consider git, DevOps, CI/CD and off we go?
PS: You might also find this interesting : https://www.grisp.org/
As someone that used real Smalltalk (Smalltalk/V), I could never get GNU Smalltalk.