Hi all, I'm the creator of SmallJS,
and was wondering why its GitGub star count had suddenly shot up :-).
Feel free to ask me any any questions here. I'll try to respond to some. Here's a short presentation that has fallen off the News page: https://small-js.org/News/Why_SmallJS.pdf
i have been trying to find an example how to run a site without build tools. i understand the playground can interpret smalltalk code in the browser, so i think there might be a way.
i would like the smalltalk code be loaded from files into the browser and interpreted/compiled there, without writing the resulting js back, but just running it in the browser.
The ./Playground project in the repo does that (taking ST source from a HTML text area). But you could modify it to open a file. (Note that browsers cannot read arbitrary files without user interaction.)
The Playground has a slightly modified version of the compiler built in to make this possible.
i don't mean opening files from disk, but fetching them from the server. i build my site as usual, but instead of converting to js in a build step, i upload the st files to the server. the html in the browser then loads the compiler and fetches the st files from the server, passes them to the compiler and runs them
Nice, a new update. I remember playing with both small-js and Amber a longtime ago. Very cool projects but I am not a JavaScript developer so I always had friction using both projects so I settled on Pharo. Off topic: if you like long running image based development you can also get that with some lisps, for example, SBCL with frequently writing a new core image file - easy to do and good for applications where you have a massive amount of in-memory persistent data you work with.
The workflow for long running lisp images is really unclear to me. It's so trivial for the code in the image to get out of sync with what's on disk.
Are there good tools that I'm overlooking for exploring the current image state? Smalltalk has that built-in but in CL I'm regularly loading my system into a fresh SBCL at least every couple days just because, at some point, some state is not what I expect it to be and I have no idea how to reconcile it.
Could you say a bit more about your workflow? I'm used to having source code files open in emacs (or zemacs) and a lisp REPL in another buffer. I edit the source files directly and then recompile changes into the running lisp. The code stays in sync because the text code files are the master copy and the running image is updated (when I choose) to reflect changes. Program state (e.g., large data structures) isn't generally kept in the source files. If what's in memory needs to be preserved, then I need to have serialization and deserialization methods, or a database, or I need to save the running image to a snapshot file. I've probably so internalized this process that there are problems with it that are invisible to me.
So SmallJS works the same way. Update text files, press Run and the 'image' is updated in a second or 2. But it contains only code, not data. And I think that's a good thing..
>SmallJS is file based, not image based, so you can develop in your favorite IDE
This project is nice, however if we don't have a specific, client-side IDE for interactive development, 70% of the power of Smalltalk is gone (one of the criticisms I give to Ruby)
How would one do to push changes to the web frontend (browser) without stopping the program ?
The Playground example in SmallJS actually does this a bit. You can compile arbitrary ST expressions within a running web page. Underneath HTML <script> nodes are created. But I didnt think it was worth it to create a fully live IDE. VSCode is very nice and compiling a change takes only a second or two, side effect free. :)
I did look at Amber before starting SmallJS. But having a full, separate IDE seemed nicer than a limited one in the browser. Amber itself has been stagnant for a few years now, alas.
I would say the main point of Smalltalk that everything is an object, including basic types and also classes (reflection). That make everything so much simpler and more consistent.
Having a 'live' IDE is nicely interactive, but it also has downsides, like a big image that stores side effects, bootstrapping issues when changing low-level stuff, and your program can break your IDE (corrupt the image), deploying an app is more complex because the image has to dangerously 'strip' itself of unneeded stuff.
So as a 'compromise' SmallJS has a very quick change-compile-run cycle of about a second or two, without the downsides mentioned above.
I wanted to try Smalltalk earlier and discovered Pharo, but I found it to be just one huge antipattern as everything involved a single combined toolchain/IDE/runtime virtual machine image. Amber's documentation seems to have screenshots of the very same object inspector.
If I want to build a wooden chair, I don't want to start by learning to use a steel metal punch to create a panel saw first...
In Pharo your entire project along with its runtime, code, data and IDE is one long lived intertwined and dispersed state. I was never really sure if this is necessarily a problem or not.
But today I had an interesting idea. Pharo is Factorio of programming. You are evolving living, functioning system using itself. And we know most of Factorio games end up as ad-hoc tangled mess, where new things are added rather on the side than old things being properly refactored. So if your Factorio factories are always pristine examples of order you should be fine with Pharo. If not, you might be better off with something like PHP or Fermyon Spin which have app state living no longer than a single request-response. With long lived state neatly and separately held in the database and source files.
I worked on an application implemented in SmallTalk for about two and a half years, and having the IDE be in the application was honestly a huge force multiplier, at least for the kind of complicated desktop application we were making. Basically, it made development extremely smooth because you always had the application at your fingertips and while developing no matter what kind of error happened it would trap into the debugger so you could see what was going on. No more remembering to set breakpoints or running under a debugger or anything; just write code, test and get dropped straight in the debugger if something goes awry. In some cases we could even fix the bug, and retry the failing operation in-flight. To stretch the Factorio metaphor beyond the breaking point, I would even say that the image-based nature helped there to be less mess, because you no longer have to care about the organization of your code in the source files: you edit methods and classes, but the on-disk organization of the bits and pieces is no longer a concern.
Where the image-based system does cause trouble is when you need to interact with stuff outside of SmallTalk. It basically doesn't play very well with others (in particular stateful stuff like database connections which can't straightforwardly be persisted when the image is saved and closed). But overall, I found developing in SmallTalk to be extremely productive, even in the antiquated implementation we were working with.
If you see code itself as state… then isn’t any program long lived state.
Richard Gabriel made some statement to that effect in his 50 languages talk, the debate between Lisp and Smalltalk being “is code state or is state code?”, both circling the same drain.
How is a docker container not a modern realization, in part, of what both camps were yammering on about years ago?
Is this some variant of Lisp's 'everything is data is code' paradigm?
For metaprogramming, I think the ideas make a lot of sense. For bizapps in the 'real world', where the rubber meets the road, I think a division of data and action make a lot of sense. For example, on my last three or four business apps I started with data models (all of the persistent state) and walked backwards into the application.
I think -- I might be wrong -- in Scheme they have 'lambda uplift' or something like that to denote various levels of meta-programming "applied", IE, some level of abstraction is "applied" or "compiled" and the code is expanded.
More immediately Scheme, many Lisps and Lisp like languages as well as e.g. Elixir has quote and unquote, which easily allows one to flip between execution and data modes.
Lambda lifting is more of a compiler design technique.
The only thing persisting in a docker container is the filesystem, and that's only until the container is killed (not just stopped). Containers are generally meant to define an initial fs image and then be more or less ephemeral (`docker commit` being a thing virtually unseen in the wild). Smalltalk images persist the state of the whole runtime, typically automatically.
There's some overlap for sure, but I don't think one subsumes the other.
Yes. Code is the state of your project. You can't avoid it. But you can parcel it, keep it in different bucket, from other stuff. That's what source files are for.
Docker is neither smalltalk vm nor lisp. It's unholy pragmatic thing, when you have ton of state but you want to cram it all in a bucket so it doesn't crawl out.
That's kind of solved with Iceberg and Metacello, they make it easy to just grab a base image and pull in what your system needs, no need to step through the change file and figure out where to file in the stuff you filed out when you broke things.
Though it's quite easy to make your application appear similar to a Factorio screen, since libraries like Roassal and Mondrian make it like a five to ten minute thing to create a custom visualisation of the involved packages. Static analysis tooling in other languages is usually not as malleable and easy to customise.
Having GUI tooling to inspect, debug and develop integrated in the execution environment is kind of Smalltalk's thing. It's like a Common Lisp with more clicking in that regard.
It's rather neat, and means you can extend your development environment in the same way you develop your applications. If you want to extend the inspector for a particular type of object you can do that. Compared to writing plugins for Eclipse or IntelliJ it's a trivial exercise.
GT does it too, though explicitly aimed at tool development rather than application development: https://gtoolkit.com/
In a sense it's the original vibe coding environment.
On the original smalltalk balloon the red, yellow and blue are in the same order as the Romanian (and Chadian) flag, so maybe the question should have been why is it not the Romanian flag?
Ralph -
Many times I have browsed past your article "About the Smalltalk
Balloon" and been tempted to add to the little bit of history that you
have there. While your link is entitled "Why a hot-air balloon is the
symbol of Smalltalk," you never really answer the question. The time
has come to tie up that loose end. Return with us now to those
thrilling days of yesteryear, and
The Real Story About the Smalltalk Balloon
Everyone in our group wanted to challenge the ivory tower image in
Byte's special issue on Pascal, because in fact we were all working
intensely to get Smalltalk-80 out the door from Xerox at the time.
The cover of that issue depicted the "land of Smalltalk" as a remote
island, and that triggered a connection for me out of which was born
the fanstasy of liberating Smalltalk from the ivory tower by balloon
ascent.
Here is the connection...
My favorite book from youth was The Mysterious Island, by Jules Verne.
It is the story of an engineer, Cyrus Harding, who gets blown far
afield in a storm during a balloon surveillance mission in the 1860's.
He ends up stranded on an island but, through ingenuity and a bit of
luck, he manages to recreate most of the accomplishments and comforts
of civilization on his own (with a little help from an amiable
orangutan ;-). Cyrus Harding became my childhood standard for
resourcefulness and the conviction that anything can be accomplished
if you are clever and persistent.
The fantasy of a balloon as the vehicle for Smalltalk's release stuck
with me from then on. When the opportunity came to design the cover
for the Byte issue on Smalltalk, I made the suggestion of the balloon
lifting off from the island shown on the Pascal cover, and everyone
picked up on it. Robert Tinney executed the wonderful graphic that we
know so well, and the rest is history.
- Dan
P.S. There is a further coincidence in this particular literary
allusion: It is revealed at the end of The Mysterious Island that the
island is actually the base of operations for a more well-known Verne
character, and that character happens also to be the childhood hero of
a more well-known figure in the history of Smalltalk.
As creator of the language and the logo...:
It is not meant to be the Romanian or any other flag.
It was indeed modeled after the Smalltalk balloon on the BYTE Magazine linked,
but simplified into 3 'basic' colors: red, yellow (iso green) and blue,
each with a slightly darker shade to make it look better.
PS I own a copy of that visionairy BYTE magazine :-).
Hi all, I'm the creator of SmallJS, and was wondering why its GitGub star count had suddenly shot up :-). Feel free to ask me any any questions here. I'll try to respond to some. Here's a short presentation that has fallen off the News page: https://small-js.org/News/Why_SmallJS.pdf
Very Cool! I had Smalltalk-80 back in the mid 80s and loved it. Prob forgot most by now tho. Just cool you've made it a thing again.
i have been trying to find an example how to run a site without build tools. i understand the playground can interpret smalltalk code in the browser, so i think there might be a way.
i would like the smalltalk code be loaded from files into the browser and interpreted/compiled there, without writing the resulting js back, but just running it in the browser.
The ./Playground project in the repo does that (taking ST source from a HTML text area). But you could modify it to open a file. (Note that browsers cannot read arbitrary files without user interaction.) The Playground has a slightly modified version of the compiler built in to make this possible.
i don't mean opening files from disk, but fetching them from the server. i build my site as usual, but instead of converting to js in a build step, i upload the st files to the server. the html in the browser then loads the compiler and fetches the st files from the server, passes them to the compiler and runs them
Nice, a new update. I remember playing with both small-js and Amber a longtime ago. Very cool projects but I am not a JavaScript developer so I always had friction using both projects so I settled on Pharo. Off topic: if you like long running image based development you can also get that with some lisps, for example, SBCL with frequently writing a new core image file - easy to do and good for applications where you have a massive amount of in-memory persistent data you work with.
The workflow for long running lisp images is really unclear to me. It's so trivial for the code in the image to get out of sync with what's on disk.
Are there good tools that I'm overlooking for exploring the current image state? Smalltalk has that built-in but in CL I'm regularly loading my system into a fresh SBCL at least every couple days just because, at some point, some state is not what I expect it to be and I have no idea how to reconcile it.
Could you say a bit more about your workflow? I'm used to having source code files open in emacs (or zemacs) and a lisp REPL in another buffer. I edit the source files directly and then recompile changes into the running lisp. The code stays in sync because the text code files are the master copy and the running image is updated (when I choose) to reflect changes. Program state (e.g., large data structures) isn't generally kept in the source files. If what's in memory needs to be preserved, then I need to have serialization and deserialization methods, or a database, or I need to save the running image to a snapshot file. I've probably so internalized this process that there are problems with it that are invisible to me.
So SmallJS works the same way. Update text files, press Run and the 'image' is updated in a second or 2. But it contains only code, not data. And I think that's a good thing..
>SmallJS is file based, not image based, so you can develop in your favorite IDE
This project is nice, however if we don't have a specific, client-side IDE for interactive development, 70% of the power of Smalltalk is gone (one of the criticisms I give to Ruby)
How would one do to push changes to the web frontend (browser) without stopping the program ?
The Playground example in SmallJS actually does this a bit. You can compile arbitrary ST expressions within a running web page. Underneath HTML <script> nodes are created. But I didnt think it was worth it to create a fully live IDE. VSCode is very nice and compiling a change takes only a second or two, side effect free. :)
Google Chrome has a 'Workspace' feature that hotswaps code without reloading the page.
See also: https://www.amber-lang.net/
I did look at Amber before starting SmallJS. But having a full, separate IDE seemed nicer than a limited one in the browser. Amber itself has been stagnant for a few years now, alas.
But isn’t it sort of the whole point of Smalltalk that the IDE and the code run at the same time in the same place?
I would say the main point of Smalltalk that everything is an object, including basic types and also classes (reflection). That make everything so much simpler and more consistent. Having a 'live' IDE is nicely interactive, but it also has downsides, like a big image that stores side effects, bootstrapping issues when changing low-level stuff, and your program can break your IDE (corrupt the image), deploying an app is more complex because the image has to dangerously 'strip' itself of unneeded stuff. So as a 'compromise' SmallJS has a very quick change-compile-run cycle of about a second or two, without the downsides mentioned above.
I wanted to try Smalltalk earlier and discovered Pharo, but I found it to be just one huge antipattern as everything involved a single combined toolchain/IDE/runtime virtual machine image. Amber's documentation seems to have screenshots of the very same object inspector.
If I want to build a wooden chair, I don't want to start by learning to use a steel metal punch to create a panel saw first...
What exactly is the anti-pattern? Just that it is image based? There is Iceberg for exporting to git afaik. Haven't used it in depth though.
I think long lived state is the problem.
In Pharo your entire project along with its runtime, code, data and IDE is one long lived intertwined and dispersed state. I was never really sure if this is necessarily a problem or not.
But today I had an interesting idea. Pharo is Factorio of programming. You are evolving living, functioning system using itself. And we know most of Factorio games end up as ad-hoc tangled mess, where new things are added rather on the side than old things being properly refactored. So if your Factorio factories are always pristine examples of order you should be fine with Pharo. If not, you might be better off with something like PHP or Fermyon Spin which have app state living no longer than a single request-response. With long lived state neatly and separately held in the database and source files.
I worked on an application implemented in SmallTalk for about two and a half years, and having the IDE be in the application was honestly a huge force multiplier, at least for the kind of complicated desktop application we were making. Basically, it made development extremely smooth because you always had the application at your fingertips and while developing no matter what kind of error happened it would trap into the debugger so you could see what was going on. No more remembering to set breakpoints or running under a debugger or anything; just write code, test and get dropped straight in the debugger if something goes awry. In some cases we could even fix the bug, and retry the failing operation in-flight. To stretch the Factorio metaphor beyond the breaking point, I would even say that the image-based nature helped there to be less mess, because you no longer have to care about the organization of your code in the source files: you edit methods and classes, but the on-disk organization of the bits and pieces is no longer a concern.
Where the image-based system does cause trouble is when you need to interact with stuff outside of SmallTalk. It basically doesn't play very well with others (in particular stateful stuff like database connections which can't straightforwardly be persisted when the image is saved and closed). But overall, I found developing in SmallTalk to be extremely productive, even in the antiquated implementation we were working with.
If you see code itself as state… then isn’t any program long lived state.
Richard Gabriel made some statement to that effect in his 50 languages talk, the debate between Lisp and Smalltalk being “is code state or is state code?”, both circling the same drain.
How is a docker container not a modern realization, in part, of what both camps were yammering on about years ago?
Is this some variant of Lisp's 'everything is data is code' paradigm?
For metaprogramming, I think the ideas make a lot of sense. For bizapps in the 'real world', where the rubber meets the road, I think a division of data and action make a lot of sense. For example, on my last three or four business apps I started with data models (all of the persistent state) and walked backwards into the application.
I think -- I might be wrong -- in Scheme they have 'lambda uplift' or something like that to denote various levels of meta-programming "applied", IE, some level of abstraction is "applied" or "compiled" and the code is expanded.
More immediately Scheme, many Lisps and Lisp like languages as well as e.g. Elixir has quote and unquote, which easily allows one to flip between execution and data modes.
Lambda lifting is more of a compiler design technique.
The only thing persisting in a docker container is the filesystem, and that's only until the container is killed (not just stopped). Containers are generally meant to define an initial fs image and then be more or less ephemeral (`docker commit` being a thing virtually unseen in the wild). Smalltalk images persist the state of the whole runtime, typically automatically.
There's some overlap for sure, but I don't think one subsumes the other.
Yes. Code is the state of your project. You can't avoid it. But you can parcel it, keep it in different bucket, from other stuff. That's what source files are for.
Docker is neither smalltalk vm nor lisp. It's unholy pragmatic thing, when you have ton of state but you want to cram it all in a bucket so it doesn't crawl out.
> I think long lived state is the problem.
If we don't use a repeatable process that can be a problem.
So treat the long lived state as cache and check that does re-build from the versioned source code archive.
That's kind of solved with Iceberg and Metacello, they make it easy to just grab a base image and pull in what your system needs, no need to step through the change file and figure out where to file in the stuff you filed out when you broke things.
Though it's quite easy to make your application appear similar to a Factorio screen, since libraries like Roassal and Mondrian make it like a five to ten minute thing to create a custom visualisation of the involved packages. Static analysis tooling in other languages is usually not as malleable and easy to customise.
That’s the core of the smalltalk-80 design: that everything in the environment is an object you can send messages to, and the OS “doesn’t exist”
Having GUI tooling to inspect, debug and develop integrated in the execution environment is kind of Smalltalk's thing. It's like a Common Lisp with more clicking in that regard.
It's rather neat, and means you can extend your development environment in the same way you develop your applications. If you want to extend the inspector for a particular type of object you can do that. Compared to writing plugins for Eclipse or IntelliJ it's a trivial exercise.
GT does it too, though explicitly aimed at tool development rather than application development: https://gtoolkit.com/
In a sense it's the original vibe coding environment.
The Lisp everyonments that predated Common Lisp, like Interlisp-D[0] and the various Lisp Machines had the same amount of clicking.
Nowadays that experience is only visible in LispWorks and Allegro Common Lisp.
[0] - https://interlisp.org/
I mean, there is a reason people don't write Smalltalk anymore xD
Yes, Smalltalk was not free-as-in-beer and library code had vendor specific differences.
Looks cool.
Why the Romanian flag?
Its not the Romanian flag (order of color is different).
On the original smalltalk balloon the red, yellow and blue are in the same order as the Romanian (and Chadian) flag, so maybe the question should have been why is it not the Romanian flag?
Dan Ingalls answer is much more interesting than anything I could explain ...
From https://lists.squeakfoundation.org/pipermail/squeak-dev/1998...
Byte cover for reference.
https://tashian.com/articles/dynamicland/byte-magazine-augus...
unless i am missing something, this is not an answer to the question
As creator of the language and the logo...: It is not meant to be the Romanian or any other flag. It was indeed modeled after the Smalltalk balloon on the BYTE Magazine linked, but simplified into 3 'basic' colors: red, yellow (iso green) and blue, each with a slightly darker shade to make it look better. PS I own a copy of that visionairy BYTE magazine :-).
This is pretty cool!
Tnx, any questions you can also ask on the git repo.
Js is the best.
[dead]