Cool! I program for around 7 months in Pharo now at Yesplan [0]. We're hiring a devops engineer and a software engineer. While the Pharo website [1] avoids mentioning it, it's a Smalltalk descendant.
What I like about Pharo:
1. Programming in the debugger makes things feel much quicker
2. Evaluating expressions inside your code editor makes programming feel much quicker
3. The ability to quickly browse classes and methods makes programming feel much quicker (e.g. I type Date somewhere, select it, press CMD+B and now I browse the Date class).
Don't get me wrong, Pharo has downsides, especially when it comes to using it in production (IMO). With that said, the language feels fun to use! I definitely like it now as my first language for side projects as it is more graphical, more playful, and feels quicker for iterative development (e.g. when consuming APIs). It's why I wanted to learn it in the first place, it has shown me a different philosophy on how programmers interact with a programming language and IDE.
Sometimes Pharo is criticized for not displaying more prominently its Smalltalk roots on its site and promotional materials. IMHO, I think the Pharo team has good reason to do so. So far it is mostly compatible with Squeak, but breaking backward compatibility is left on the table as a possibility in the future. So they applied the lesson Perl folks had to learn the hard way, until they perceived it was better to recognize Perl6 as a new language and rename it to Raku. When developing new things, calling them by old names sets expectations and causes people to make lots of implicit assumptions.
The way I like to deploy a Smalltalk backend service is when developers have their cloned git repos and follow gitflow, one new directory for a new branch, so they can:
1. Build a local image intended to help with 1 branch (branched out of fresh cloned develop).
2. Add changes, unit and system tests for TDD/regression defense/coverage.
3. Commit and push code to share with the teammates.
4. Open PR to develop when ready/PR's approved
5. Eventually merge develop into master and version bump for release
6. The PRs running CI/CD pipelines with the full battery of tests and
7. The final docker image that devops can consume at will for deployment under their load balancer or whatever architecture they had setup.
In this style, images generated by work on bugfix or feature branches are optionally disposable after its PR. The dev can choose to archive or not.
The image is just an in memory representation of the code. At any point one can export the code representation in the image to an external text file in a number of different formats. These external text files can be version controlled with Git or any other VCS. In turn the the text files can be imported into an image as well. I never worked with Smalltalk professionally but I imagine deployment works in a very similar way to the deployment pipelines you might be used to.
Start with a base image, import code pulled from the VCS repo, start the image, run some test verifications and copy the image to its designated virtual insurance host.
Typically, a ST image is a combination of the base image, and the change set applied to the image. The change set can be code loaded in from an external source, or someone hacking in the system. By default, all changes made to an image are serialized to a changes file. That way, if your image implodes, you can start with the previous image and roll forward your changes.
That said, projects in general are NOT change sets. They're just collections of classes serialized out as ST source code. These source code files capture the state of the source code within the image, but not the state of the image itself.
Done properly, you don't have any aspects of the source code depending on some existing state within the image, but not captured in a class. But, you don't know that for sure. All of the source code relies somewhat on the vast amount of global state within the image. If global variables make you itch, well, let me introduce to you an ST image.
Pharo is a fork of Squeak, and it's distributed as an image.
Now the Pharo folks have done a lot of VM work, but even in the beginning I imagine that having a chain of custody of source code that converted a stock Squeak image into a nascent Pharo image probably never existed.
I bet even with their long github history it would be very difficult to generate later Pharo images from source code checked in to github.
The ST image is a ball of clay that the developers add to and cut away from in an ad hoc manner. I'm sure they strive to repeatability and such, but I imagine it's not really a high priority for them when some sneaks into a core developers image (which can be from their work, or changes merged from someone else).
Having been raised in a world of "make clean install", where the finished product is a deterministic result of all these pieces I can see and touch, the ST image world has always made me a bit uncomfortable.
Obviously the users cope, and it's a "me" thing, but there you are.
it's not only a code, it's a also current _state_ of the system, no? some kind of root/singleton objects, their instance variables, etc. I mean, for a web application most state should be in a database, but this takes some discipline.
And importing updated code to a live system sounds like a black magic. What happens while it's still in progress? Or does one have to start a new process, like we do in other frameworks? Erlang has live updates, but I imagine live update in smalltalk works very differently. So many questions!
The short answer is: just try it, you are in for a lot of fun and puzzles.
If you have Windows nearby I would recommend Dolphin Smalltalk due to a great system browser.
> it's not only a code, it's a also current _state_ of the system
There is no difference in Smalltalk. The code includes all the created instances with current field values.
> updated code to a live system
From the user point of view everything is simple, yet the simplicity is the advantage of the compiler, not the user. If you update the code the instances that you upgrade run the new code, and if you don't upgrade the old objects they run the old code.
I don't know much about deployment. In terms of version control, we use git. I find it a bit tricky though as there's a git repo inside the Pharo image, and then there's the file based git repo and they need to be kept in sync. I've gotten used to that though, but it's not ideal.
Every developer has their own image. It's easy to set up an image (though I always need to check the company docs on how to exactly do it), but then you download your own image. These images can be different from each other as well, as only the code checked in to git is the same.
I posted a talk on HN recently about four programming languages from the 1970s - Smalltalk was one of the languages discussed.
Smalltalk has a object-oriented programming model (OOP) with notable differences to the more familiar OOP model from languages like Java and C#. Smalltalk also has an windowing IDE (eschews separate text files), a consistent model, and minimal syntax (just 3 keywords). It's a very interesting language.
> with notable differences to the more familiar OOP model from languages like Java and C#.
This only applies to Smalltalk-72 (which is celebrated this year). The Smalltalk we know today started with Smalltalk-76; like Simula or Java it has inheritance and compiled virtual methods (i.e. no longer passing tokens to objects for interpretation). Smalltalk-80 celebrated its 40 years in 2020 on which occasion I implemented a couple of tools and VMs to study its inner workings, see https://github.com/rochus-keller/Smalltalk.
> a consistent model, and minimal syntax
Which is mostly beneficial for the parser writer; implementing an efficient VM for Smalltalk is still an art today, because nearly everything is a closure and the control flow has to be guessed; in any case Smalltalk can at least pride itself on having initiated a development that led e.g. to Java Hotspot and the V8 engine.
Smalltalk is one of my favorite languages and definitively a great one to teach real Object Oriented Programming.
Off topic: the documentary seems interesting, but I hate the narrative: basically, "Jobs/Gates stole" and "we were the rightful knights inventing computing, but now it's used for Games/Porn/Chat/Leisure ergo it's bad". Kind of gatekeeping. Computers evolved and they're everywhere. Sequencing protein chains and also behind Candy Crush.
I would love to see a modern Operating System built off of SmallTalk. I tried out Pharo recently and I was amazed at its ability to introspect (reflect?) into any ui element in the running image and see/change the code for that element. I think building an entire Operating System on this concept would be really cool. The level of extensibility we would get combined with the ease of extending the OS would lead to some pretty awesome changes.
To get around some of the common pitfalls of new Oses it could use a rump kernel and leverage the drivers from Netbsd, and it could be developed on an SBC making it easily accessible to people to run on actual hardware
I agree with you. One “what if” possibility that I think about from time to time is an open source community back in the 1990s rallying behind an OS built from Smalltalk or a language environment offering similar capabilities such as Self or Common Lisp. I figure a Pentium or PowerPC personal computer from circa 1994 should have enough power to drive an entire ecosystem of applications around Smalltalk, especially with the compiler and virtual machine innovations the Stanford/Sun researchers working on Self made. The environment’s introspection and metaprogramming capabilities would have resulted in a highly flexible, extensible system, but with a simpler and cleaner design than contemporary Windows and Unix desktops, which have many layers of complexity.
Recently I’ve thought about making a Smalltalk- or Common Lisp-based operating system with the features you mentioned, but I ended up changing direction when dealing with the problem of interoperability among different languages. As appealing as Smalltalk and Common Lisp are, many people prefer different languages, and unfortunately different languages have different semantics, making interoperability difficult. I prefer a protocol-based approach to interoperability. I’m right now experimenting with Plan 9, an operating system designed by many of the same people who worked on Unix at Bell Labs, and seeing how I can implement reflection and metaprogramming through Plan 9’s “everything is a file” facilities, and also how I can take advantage of the 9P protocol to enable component-based software design. Some more of my ideas can be found at www.mallowos.com.
A recent start on this could be the NopSys/CogNos project, which built a standalone Smalltalk system on x86 a few years ago. There are GitHub repos[1,2,3] and a paper [4] where the authors write "there would certainly be much more work needed before one could consider deploying our system." The project seems to be inactive now.
Though, from the outside, it's not particularly clear what's what amongst all the differently named versions, and which direction it's being driven in these days.
This article is a painful reminder of the demise of the Living Computer Museum in Seattle, where one used to be able to play with an actual Parc Alto :-(
As someone who learn programming relatively late, the only thing i know about Smalltalk is it highly influenced Python. However, I just checked Wikipedia article about Python [1], it has no mention of Smalltalk. Did I just remember it wrong or there is more to it?
> the only thing i know about Smalltalk is it highly influenced Python
Which is wrong. See e.g. http://python-history.blogspot.com/2013/10/origin-of-metacla...: "I was only vaguely aware of Smalltalk at the time; I remember being surprised by its use of metaclasses (which is quite different from that in Python or Ruby!) when I read about them much later."
I think you remembered it wrong. I personally have never heard of such a connection. Python is somewhat notorious for ignoring languages like ML, Lisp/Scheme, and Smalltalk dialects.
"Python's predecessor, ABC, was inspired by
SETL -- Lambert Meertens spent a year with the SETL group at NYU
before coming up with the final ABC design!"
--Guido van Rossum
Also heavily influenced by C, its first implementation language. Many modules and interfaces are thin wrappers to C. Think os, socket, select, string method names, etc.
I wasn’t aware of a Python connection (not saying there isn’t one) but Smalltalk definitely influenced Ruby. I think if it as a more direct descendent with the way objects pervade it and how “everything is an expression.”
At Yesplan [1] we use GemStone in production, we use Pharo for development. The languages are quite alike, but we do need to have a compatibility layer between the two. For example, GemStone doesn't have dynamic arrays (arrays that evaluate expressions of each element).
Our CTO knows companies that use Pharo in production. I'm sure there are also people using VisualWorks in production. All of these languages are Smalltalk descendants.
The productivity that a handful of good smalltalkers can achieve to solve complex systems is off the charts.
The strongest thing that Smalltalk has is that you'll feel really powerful to deal with changes in the rules of scenarios that are high in complexity. So speed in adapting to change fast is what I see as its most valuable trait.
> The productivity that a handful of good smalltalkers can achieve to solve complex systems is off the charts.
You could say that of any experts in any system. They will be extremely productive.
There is really nothing special about Smalltalk that makes its developers automatically more productive (especially not the IDE, which is vastly outclassed today by the likes of IDEA, XCode, and Visual Studio).
Indeed, however that is transparent to the user, the current IDE experience would be similar to getting out of Smalltalk and restarting it from scratch.
Do they haven't, not at the level that Smalltalk does it.
To affirm otherwise only reveals lack of experience on the matter.
No Smalltalk environment has ever shown an error message about not being able to do edit-continue/hot-reload/whatever.... after doing a code change in a debug session.
Nor are they capable of transparently exposing their internal structures in the debugging session.
Can you halt and open an interactive debugger in a green thread in a running production node that you can correct a method and let that thread continue running after that with these? Without interrupting any other thread of that node of course?
> No matter how you use .NET Hot Reload please be aware that some changes are not supported at runtime and will prompt you with a rude edit dialog and require you to restart your app in order to apply. We’re still working on the feature and the documentation to detail what edits are supported. For now, start by reviewing our existing list of Edit and Continue (EnC) equivalent capabilities. Since Hot Reload is powered by EnC this will give you a good starting point for better understanding this new feature. For details see: EnC documentation.
In Smalltalk environments since the early 80's, it always works, there are no buts and ifs, or extra products to install.
As mentioned on another replies, it only shows you never used Smalltalk in production.
Yeah, I’ve programmed (not professionally) quite a bit in the various free Smalltalks and from a purely development perspective I could easily see it as a competitive advantage. The big question I would have is performance of the VMs and images under load but I guess that would fall under premature optimization. I imagine horizontal scaling or transitioning to Gemstone when needed would be the answer.
When you hire someone with experience in an esoteric or obscure language, there is a reasonable chance the person really likes learning esoteric or obscure languages. This is usually a plus.
In a previous job I worked on the case management software used by the Norwegian police. It was first put into production in ‘96, based on an earlier system from I think ‘94 (thus the Smalltalk). All criminal complaints in Norway pass through this system.
As a developer, I found the system really nice to work on, despite an antiquated Smalltalk implementation at the base (end of lifed in ‘99). Since the IDE is integrated into the running application, the development process was extremely smooth for a desktop application like that. But the process was an acquired taste, not all the developers got into the groove.
Yes. At https://telna.com/ we have it in a backend that in last july it was helping to route half petabyte of network traffic and is expected to reach 1 PB by the end of this year.
- OOP is message passing
- The interactive environment
- Surprising things about Smalltalk
- Did Smalltalk achieve its goals?
- Failure of Enterprise Smalltalk
No longer true since Smalltalk-76, which has virtual method dispatch like Java. What you refer to is probably Kay's philosophy which is something else than the Smalltalk implementation we know today.
Can you elaborate on this because this has been bugging me for some time. I’ve heard Kay’s comment many times but I have never heard him give an explanation as to what practical difference it would make in the day to day task of software development, specifically with respect to Smalltalk 80. When I think of message passing I think of things like Kafka, message queues, ESBs etc. Where the producers and consumers of the messages are completely decoupled and the processing is asynchronous. But I’m not sure how this maps to a thread/proc local context where a caller of a function or method or the sender of a “message” expects a response.
Kay's view of object-orientation is "messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things" (quoted from http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...). This is quite different from what we associate with object-orientation today (objects, classes, inheritance, virtual methods, etc.), and how it was implemented e.g. in Simula 67, or in Java. Kay's view has similarities with Hewitt's actor model (see e.g. https://www.quora.com/What-is-the-difference-between-Alan-Ka...). A good source on how Smalltalk-72 was different from Smalltalk-76 is Ingall's 2020 paper (https://dl.acm.org/doi/10.1145/3386335). Smalltalk-72 indeed implemented a kind of message passing in that there were objects "sending" token streams to other objects which interpreted these streams; so there was indeed something like a "message", and there are similarities with message queues and parts of Kafka; message passing can be synchronous or asynchronous. Calling a method is not the same as passing a message; there is no message which has to be "interpreted", but the compiler knows the signature of the method and generates efficient code for calling it using a specific ABI. If methods from objects are called which reside in a different address space/process or even on different hardware, then method calls are dispatched over an IPC mechanism or even a network (like e.g. CORBA or some versions of ESBs); the network dispatch is technically message passing, but to the programmer it still looks like a local (synchronous) method call. The Smalltalk community instead prefers to talk about "message passing", even if it is implemented as plain in-process, in-memory method call. It is also notable that already Simula I (1962) had "active objects" (the Simula I objects were called "process") and there was the notion of events and queues.
You're talking about the internals and optimizations. Smalltalk still uses message passing as the concept, even if it doesn't send an actual a message for the recipient to parse under the covers.
That's how you can trivially have distributed objects, instances responsing to methods they don't directly declare and know about, etc.
Well, "dog" is just a name we give to a specific set of attributes, so no, the dog wouldn't still be a dog (in the sense that the word "dog" would not communicate what he is to another person).
In this case, even acceptaing post-76 Smalltalk doesn't implement "real" message passing unver the covers, we not only call it that anyway -- so one would be justified to say:
"real X is what we call X, not what originally we call X, or what the etymology of X implies"
but it also behaves like it. So one would be doubly justified to say it is (in the "if it walks like a duck, and quacks like a duck" sense).
In other words, in this, I think you're making the same mistake you accuse Kay of making with regards to OOP ("C++ and co is not real OOP" -- well, it is now, as that's what we describe as OOP nowadays).
"perform" is a method of the Object (i.e. Integer super) class, the argument is a symbol; this call just does a second method dispatch, i.e. "perform" does yet another dispatch on the Integer object and then calls the "factorial" method; so no, neither this is message passing; it's rather like Object.getClass().getMethod() and Method.invoke() in Java.
huh? That makes no sense to me (I must be missing something here).
'perform' is indeed a msg. The integer object doesn't need a 'perform' method in order to do something with that call. Its entirely up to each object to decide how it wants to deal with a msg. Including those msgs for which there isn't a corresponding method.
In other words, the caller has NO way of knowing (or enforcing) what the object its sending a msg to, does with that msg. Eg: based on certain runtime conditions, an object can reconfigure itself at runtime, and simply proxy certain messages to another object, potentially running on a different machine, and relay the results back.
Why should "perform" be a message? It's just a method of the Object class, which is the superclass of Integer. You can use my St80ClassBrowser and St80ImageViewer (see https://github.com/rochus-keller/Smalltalk/) to check the ST-80 source code and image if you want; there is a list of all selectors (i.e. method signatures) and the classes which implement them. Going up the class hierarchy when doing virtual method dispatch is a fundamental concept of all object-oriented implementations; in contrast to e.g. C++ this can be done dynamically at runtime in Smalltalk or Java (which is also called late binding). In contrast to Smalltalk in Java the class loader verifies that a method for the referenced signature actually exists; in Smalltalk you can try to dispatch any signature which can result in a call to the doesNotUnderstand method of the Object class; the same could also be achieved in Java with a custom class loader, but usually you want to avoid it.
As a counterpoint, I would suggest looking at Jeff McAffer's CodA project. It defined a group of 7 metaobjects to define the behavior of each object, six of them for message passing and one for accessing state. He couldn't patch the commercial VisualWorks virtual machine and used #doesNotUnderstand: tricks to make his prototype work. It wasn't fast, but showed that the semantics were correct. Here are the message passing metaobjects he defined:
- Send: prepares a message to be sent and negotiates with the receiver
- Accept: negotiates with the sender
- Queue: can save accepted messages to be handled later
- Receive: deals with queued messages
- Protocol: can associated the selector in a message with executable code
- Execution: knows how to used system resources to actually do what the message asked
The default metaobjects are 100% compatible with Smalltalk-80 base level code but his thesis show several interesting alternatives.
There is no doubt that you can implement a message passing system in Smalltalk, as you can with any Turing complete language. In Smalltalk instead of "calling a virtual method" people just say "sending a message". But it actually works quite similar like e.g. the Java VM. Params and receiver object are evaluated and pushed to the stack, then the method is looked up in the receiver class using the selector (which is an internalized string) and then calls the method with the given parameters (this lookup and call is called "send" in Smalltalk); the major difference is that in Java the verifier checks whether a method with the given name and signature actually exists in the class when it is loaded; but also in Java you can influence the dispatch as you described and e.g. create your own class loader.
While you can implement message passing on top of any language, as you said, I was talking about doing message passing under Smalltalk-80.
There are non messaging parts in Smalltalk-80, like assignment. The Self variant of Smalltalk goes quite a bit further in using message passing for everything.
>But there is also a pertinent body of knowledge that is taught and tested at universities, which includes an accepted terminology.
Well, speaking of universities, can you find a univercity-level course/book that doesn't characterize Smalltalk (post 76 too) as having message passing?
> how will looking at Smalltalk-80 source code show us what "true" message passing is?
Not at all; but you can look at the Smalltalk-72 source code.
> Do you mean like Erlang?
Examples of "true" message passing are e.g. SOAP or MPI. Erlang is an example where message passing is indeed part of the language; another example are Go channels.
My guess is that very few people care to learn anything about Smalltalk-72, and simply saying you mean something like SOAP or Erlang will clearly communicate what you mean by "true" message passing.
If your interest is point-scoring maybe say Smalltalk-80 is simulated message passing or faux message passing ;-)
The original name for Smalltalk was "Slogo" for "Simulation Logo" (like Simula was for simulation in Algol). It also reflected the expected performance of the first implementations.
Download Pharo or Squeak and start playing with it. Both (iirc) come with tutorial stuff. Or, if your feeling more adventurous, try Glamorous Toolkit (gtoolkit.com) which comes with has tons of teaching material (in the tool itself) -- also well worth investing some hours in watching some of their videos.
What I like about Pharo:
1. Programming in the debugger makes things feel much quicker
2. Evaluating expressions inside your code editor makes programming feel much quicker
3. The ability to quickly browse classes and methods makes programming feel much quicker (e.g. I type Date somewhere, select it, press CMD+B and now I browse the Date class).
Don't get me wrong, Pharo has downsides, especially when it comes to using it in production (IMO). With that said, the language feels fun to use! I definitely like it now as my first language for side projects as it is more graphical, more playful, and feels quicker for iterative development (e.g. when consuming APIs). It's why I wanted to learn it in the first place, it has shown me a different philosophy on how programmers interact with a programming language and IDE.
[0] https://yesplan.be/en/vacancies
[1] https://pharo.org