This should really be "Why every developer should learn Smalltalk." Dan Ingalls gave a keynote at jsconf demoing Lively Kernel, a SmallTalk-like, image-based, in-browser IDE written in JavaScript. His demo received a standing ovation and was the thing I heard talked about most during the social events.
We're obviously not far from being able to have SmallTalk-quality interactions with things we build in the browser. Brent Victor's recent talk has spurred a lot of work on more-interactive development environments, some of them in the browser.
I would really like an old SmallTalker to spend some time researching and thinking about the old tools they had: which were valuable, which were more trouble then they were worth? What mistakes did they make that they wish they had done differently? It would be an excellent briefing for the next few years of work on the web.
(A small note: it's traditional to not capitalize the t in Smalltalk. Old-timers take that as a signal that text was written by a non-dev.)
thinking about the old tools they had: which were valuable, which were more trouble then they were worth?
A seasoned Smalltalker would have spent more time talking about the Debugger. I was teaching a Smalltalk class once, and this one student who was a quant from a New York financial firm just spontaneously exclaimed: "This debugger is from God!" It was very fast, responsive, and was "well integrated" with the environment. More on that...
EDIT: As I took the time to say elsewhere, there really isn't that much "integration." It's more that the environment is so minimalist that it lacks many barriers present in other environments. Just about every single instance of every object has the equivalent of a REPL, and finding a particular instance in the middle of runtime debugging typically takes just a second.
Even the "IDE" really isn't one. (And I should know, because I've written a good portion of a commercial Smalltalk browser.) Aside from the refactoring mechanisms, it's a pretty lightweight and basic browser on objects -- it just so happens they're the meta-level.
What mistakes did they make that they wish they had done differently?
A big mistake: exorbitant per-seat developer licenses, and positioning as the "secret weapon" of the Fortune 500. Another oft-cited one was the Parcplace/Digitalk merger and the ensuing conflicts. Most of the mistakes had to do with community and how the ecosystem did/didn't interact with the rest of the programming world. Technologically, there was a lot of goodness.
Even better is the interaction between the test runner and the debugger. Unit tests are orders of magnitude more useful when you can just open a debugger on a failing assertion.
Not to mention the integration between the debugger and Seaside...
I always get a few jaw drops when I fix code and the page comes up once I press "Proceed".
The thing is, that's not really "integration." That's just the Debugger doing what it usually does. There's no abstruse code supporting that. (Usually Smalltalk environment "integration" does require a few lines of pedestrian code.)
Well, Seaside does have explicit code to support the debug link. If you get an exception during rendering, the framework generates a 500 response with a "Debug" link. Clicking the link restarts the previous request, and when it hits the exception, it opens a debugger instead of generating the 500 response. If you fix the error and continue, the page is sent to the browser as usual.
Thanks for both the small note and the big suggestion. What did the debugger have that made it "well integrated"? In JavaScript, we have fairly good graphical tools in Chrome. One headache is debugging asynchronous code, and a good debugger could track not just the current call stack, but the deeper "reason" why this code is running, including timers, events, xhr callbacks, and let us jump between those levels as opposed to just the function calls.
What did the debugger have that made it "well integrated"?
It's more what the environment didn't have. Everything, including almost all of the meta-level (and by almost, I think it's just 3 Classes that are treated specially by the VM) was just an ordinary object. Even throwing an exception was just Smalltalk executing as usual. Basically, there were no barriers.
(EDIT: An example mentioned elsewhere -- the integration between the Debugger and Unit Tests. It's not rocket science. You just catch an exception and pass an object to the Debugger.)
One headache is debugging asynchronous code, and a good debugger could track not just the current call stack, but the deeper "reason" why this code is running, including timers, events, xhr callbacks, and let us jump between those levels as opposed to just the function calls.
It wasn't unusual in VisualWorks for us to have multiple call stack open at the same time. (In fact, some people would put code to evaluate in comments, which could be executed in the midst of another debug session.) Timers, events, Semaphores -- these are all just Objects, subject to the same kind of manipulation. This isn't to say there wasn't some pain around concurrency, because there was that. But a competent programmer felt confident about dealing with it, because she/he had such responsive tools and no barriers to what they could do and see.
All the usual ones. You could very well hose your image. The nice thing, though, is that you could just kill your process, restart the image, and recover all of your code changes.
You could also have a Smalltalk "Process" (or green thread) starve the other ones. Lots of Smalltalks are single-threaded. VisualWorks is too, but has tricks for calling out to DLLs with a separate thread.
Basically it boils down to the semantics of the language. Languages like Java and C# can be well supported by IDEs because the syntax is declarative. A class definition in Java isn't executable, it's just data that describes the class.
In Ruby, on the other hand, a class definition is executable. That makes meta-programming easy (eg. ActiveRecord's #has_many), but it makes tool support difficult. An IDE can't just parse the source code, it has to actually execute it find out what classes are defined.
But that's a huge can of worms! What if you wrap your class definition in "if Date.today.tuesday?" What if the script has side effects you don't want to trigger every time you open your IDE? On the other hand, once the metaprogram has executed, the program that actually executes at runtime isn't something the programmer wants to see. Imagine trying to work with a Rails app that had all the the metaprogramming flattened out of it? Tedious.
What's unique about Smalltalk is that it has both executable class definitions and an IDE. It works because the IDE only lets the programmer work with the runtime representation of the program, and not the on-disk representation. The whole ecosystem - language, libraries and tools - are designed around that paradigm.
An IDE can't just parse the source code, it has to actually execute it find out what classes are defined.
There have been a few -- I think more than 3 -- Smalltalk projects where the parser was modified so that Class definition and other code could be executed but only result in a "shadow" Class being instantiated, so that the code could be browsed before being committed to the actual image.
only lets the programmer work with the runtime representation of the program, and not the on-disk representation. The whole ecosystem - language, libraries and tools - are designed around that paradigm.
It should be possible to have it both ways with Ruby. ObjectStudio Smalltalk had declarative class files. You don't want the runtime changes to be written back to the declarative files, however. This caused lots of problems in ObjectStudio. A better approach would be to have some way of flagging the runtime change, perhaps by outputting another file, then let the user merge changes back.
From the blog post.
I'd much rather see a Smalltalk that let me create small, headless images, tens or hundreds of kilobytes in size, with just the little bits of functionality I need for a particular task. If they had good libraries for file I/O, processing text on stdin/stdout and executing other commandline programs, they'd fill the "scripting language" niche very well. If they could be created and edited by a larger IDE image, they'd have the Smalltalk tools advantages as well.
Apparently someone at Digitalk did exactly this years ago, with images as small as 45kB. I think the project was called "Firewall." This technology will never see the light of day, but it shows what is possible.
The example is illustrative, and a ruby code in the wild will generally use positional arguments or pass hashes around, rather than implementing weirdly named methods:
That is not to say weirdly named methods aren't used. Activerecord dynamic finders are one example that comes to mind `Model.find_by_first_name_and_last_name`, but they are named so to provide information to method_missing hook.
> If you need to pass multiple blocks to a method in Ruby it always looks clunky and probably that's why it's not a common idiom:
I don't think the examples are clunky at all. It is similar in all languages which treat functions as first class datatypes.
In ruby, you use "one block" or pass multiple lambdas. It isn't any different from smalltalk example, except for superficial syntactic difference.
> When you start writing a new app in Smalltalk you don't open Emacs or RubyMine you launch a VM.
I don't know much about Smalltalk, but this IDE/VM approach must be damn substantive to make up for not using Vim. The way the article puts it makes it sounds like "don't open Emacs" is a positive, which is seldom the case with people who use a lot of emacs/vim.
I don't know much about Smalltalk, but this IDE/VM approach must be damn substantive to make up for not using Vim.
The thing about the IDE, is that there's hardly any of it there. It's all just objects that each effectively have their own REPL, and you're directly manipulating all of them.
You can actually start writing a debugger in most Smalltalk environments, and you'll have something that lets you browse a stack trace in under 5 minutes. (If you know the API for dealing with stack traces. A newb or someone out of practice will take longer, but most of it will be reading the API.)
An engineer I know was bored in his "Intro to Smalltalk" class and spent 10 minutes writing a tool that compiles and evaluates code. The exact same code made it into the production "IDE" and was there for over a decade.
The thing is, there's such an amazing amount of "integration" in the environment, you'd think there was tons of ingenious code written by teams of geniuses, but there isn't. It's just that a lot of unnecessary stuff has been removed and made runtime, so everything is available for you to see and change.
It's one of the best examples of how minimalism can work very well.
There are lots of good points made here, but I'll add one: write the environment in itself. The original vision for Smalltalk is that you would be using some application, get curious about how it worked (or want to change it), press ctrl-C to start a debugger, start reading code, start editing, get curious about how the debugger works, press ctrl-C again, start reading code, start editing... That smooth progression from application user to programmer to tool developer was a conscious design goal of Smalltalk (also of Lisp), and has gotten lost somewhere along the way. Once you take responsibility for your own tools you quickly learn to use your new-found powers sparingly, but it's a completely different feeling being a programmer in an environment you can modify than being a programmer in an environment someone else made and you can't touch.
I love reading introductions to languages. But holding them up in comparison to just one other language is often problematic. I don't think this article does ruby much justice (e.g. the syntax stuff, and especially the bit about ruby's lack of debugging tools: https://github.com/pry/pry). I found myself wanting to defend ruby. Which is very distracting, and entirely beside the point, because really I just wanted to learn a little bit more about smalltalk.
I guess the point of the author is that no language can have a debugger as powerful as Smalltalk's, as having the code, the state and the tools live in the same environment is the only way you can go as deep as Smalltalk debuggers go.
If you're editing your code in an editor, running it in an interpreter and storing the state in your RAM, there's no way your editor is gonna be able to stop at a point of your stack to let you modify a piece of code live, or add a method, or override an operator, or change the class of a living object and continue as if nothing ever happened.
It might not be as polished as the Smalltalk tools yet, but there's no inherent problem doing this with Ruby. There might be some things you can't do in pure Ruby, such as perhaps replacing a class pointer to actually change the class of an object, but low level hackery like that is easily enough done with a small C extension - I've poked around in MRI's C-level view of the object model before and it's pretty simple.
I used to do smalltalk for a job (internship, but still learned a lot). I love it, it's a terribly under-appreciated language.
I think what ended up sidelining it was that it didn't really integrate well with the rest of the system. Part of this was the syntax, even though you could bridge it with C, it was awkward. IE, "something.f(a,b,c)" would become "something f: a with: b with: c". Smalltalk's syntax is really cool when you're just working within the smalltalk system itself, but at the edges it gets clunky.
The other problem is smalltalk just seems to like living in its own world. Even now that's largely the case. (Fun challenge: try making a smalltalk app that isn't easily recognizable as a smalltalk app.)
Given what Clojure is to lisp, I hope too there can be a "Clojure for smalltalk", if you will. Something that captures what's really cool about the language but throws away the historical baggage and makes it integrate well with the rest of the system.
> Fun challenge: try making a smalltalk app that isn't easily recognizable as a smalltalk app.
It is true that both Lisp and Smalltalk make it very easy for people to build things that would normally take a team and an architecture. This has the down side that if it's easy to build something that acts sort of like a button, that's what ships rather than bridging to some OS button. It's a lot of work to implement for no obvious benefit, especially to the Smalltalk programmer who is using the system because they like it and don't mind the differences. This seems like exactly the sort of thing that would make for-pay Smalltalk systems viable, but nobody seems to be willing to pay for a language now. Even if it would be cheaper in the long run, it's harder to do the math and it's hard to compete with free.
> I hope too there can be a "Clojure for smalltalk", if you will.
I think this is a concept that should be explored in more depth. Some things I'd toss out as worth discussing:
- Having a standard library or syntax for defining classes (GNU Smalltalk addresses this)
- Real namespacing, because I'm sick of seeing XXYYZZClassName
- Sexy, dirt-simple FFI to C or Java. Probably, as you point out, through a standard calling convention for external stuff (maybe borrow the Block API, something f value: a value: b value: c).
I think apart from these things you could really build the Smalltalk of tomorrow in the Smalltalk of today. You need really good OS integration, especially graphically but every other way as well. You probably need to be able to serialize the system to ordinary flat text files so you can use modern VC.
I know Juan Vuletich has been rebuilding the standard image his way from the ground up with Cuis but as far as I can tell progress is stalled. Other than that I don't know of any big project besides Pharo, which is even more modest, really just about removing crap from Squeak and producing a professional shame-free open source Smalltalk.
> ..., it's a terribly under-appreciated language.
I read somewhere that Java is to blame for that. As Smalltalk was finally gaining a footstep in the enterprise, Sun's marketing was able to convince managers to replace those projects by Java.
Eclipse design was initially based on Visual Age for Smalltalk. Actually you can still make use of a Smalltalk like browser in Eclipse.
>Fun challenge: try making a smalltalk app that isn't easily recognizable as a smalltalk app.
This can also be said of other GUI libraries. Back in the early 80-90's it was very easy to recognize Clipper, Turbo Vision and OWL applications, as the developers seldom changed the default L&F.
Objective-C certainly borrows the syntax, but that syntax is a second-class citizen in the C world. That removes its negative bits (interoperability), but it also removes most of its positive bits too (ie, uniformity, being able to construct new language primitives, everything-is-a-message, etc.))
My point was that the colon infix syntax, which you seem to be claiming is awkward (but maybe I don't understand your sentence construction) is something a lot of people actually consider a feature.
This is one of the reasons I like objective-c. Lots of people hate its verbosity, but I love that you can almost read it like english (assuming you name stuff sanely).
A word of caution... :) I had a similar experience with Obj-C and decided to give smalltalk a try. After a brief struggle and period of wetware refactoring, I can longer stand to work in anything else.
Can anyone provide a suggestion on what to use to learn Smalltalk under Windows? The article mentions both Squeak and Pharo, of which only I've used Squeak briefly in college, but there I really had a hard time with the interface. At least I felt like I completely hosed my Smalltalk VM more than once. I have not tried Pharo. It appears that there is also Dolphin Smalltalk.
I've used Squeak briefly in college, but there I really had a hard time with the interface.
Well, they have a "burn the diskpacks" philosophy, so the interface is very different and changes a lot of conventions.
At least I felt like I completely hosed my Smalltalk VM more than once.
This is something very different and weird you'd have to get used to. Hosing your VM is actually no big deal. There's a way to recover from that quickly without losing any source code changes. I would try Pharo. Dolphin was a nice environment, but that was so long ago.
(Since Smalltalk gives you the power to do anything, even with your meta-level, it >has< to work like this. Otherwise, people would feel timid about manipulating their meta-level.)
At this point, I'd say Pharo is the most actively developed, and the most polished, of the open source Smalltalk implementations. There's been a fair amount of work cleaning up the UI since they forked from Squeak, and the free ebook "Pharo By Example" has a good overview of the UI and development tools in the opening chapter.
Squeak, Pharo, VisualWorks and Dolphin will all work fine on Windows.
Squeak and Pharo (and VisualWorks to a lesser degree) have non-standard UIs that will be (a little) unfamiliar to Windows users. Dolphin's UI should be the most familiar.
It amuses me greatly to see it point out how much more readable Smalltalk's method syntax is (i.e. "it skips the . operator") immediately before launching into an example of how great Smalltalk is that it doesn't have an if() construct and needs to define methods to dispatch on conditions.
Smalltalk is great (mostly for historic reasons these days) and definitely worth learning. But that bit is cognitive dissonance at its best.
Smalltalk is great (mostly for historic reasons these days)
In my experience coming to Pharo Smalltalk after a 15 year journey through C, C++, VB, PHP, ObjC, and Ruby (my second favorite lang), I can say that none of the reasons I find Smalltalk awesome are historical. This idea that one should "learn Smalltalk to bring those lessons with you to the language you 'really' plan on using" is a silly idea, often repeated.
Most importantly, Smalltalk is an environment, not a language...
The Smalltalk community is full of talented developers doing cutting edge research and serious commercial applications. We use Smalltalk, for example, because its live, open, dynamic environment makes it a joy to use and blows productivity through the roof. Having complete control over the IDE is a dream - as a small example, when I got tired of constantly navigating to my default code directory, I added a default setting to Pharo Smalltalk, in about 5 minutes, so I and every other user could benefit. This kind of enhancement is routine because it's so damn easy! Even in Ruby, it's a hassle to dig through a lib's source files and find the code to edit. In Smalltalk, one can drill down through the UI (from menus, windows, etc.) into the actual code, or set a breakpoint launching a debugger on the running system. What other OS (Squeak/Pharo can run on bare metal) lets you do that, all in the same language?!
Ruby is a language, not an environment. So why are you comparing Smalltalk environment to a language? (this applies largely to the original article as well - if you want to compare languages, compare languages; if you want to compare environments, compare environments).
There are Ruby environments that provide fairly deep introspection and live changes to a system, like Pry. It's just not the main way of doing things. For a reason: It's not the way most developers are used to working.
You are asking to force the question into an artificially created box that doesn't help us get to the truth. The Smalltalk experience is naturally - and more fairly - compared to Ruby as an experience.
They are both tools, and thus we're primarily concerned with their utility, not inherent value. One wants to know: how will these tools help me to achieve my goals. The answer is that the turtles-all-the-way-down experience of Smalltalk helps devs achieve those goals more quickly, easily, and joyfully.
p.s. Thanks for pointing out Pry! I didn't know about it and it looks really cool :) As it relates to this conversation though, a more-advanced repl is stone-age technology.
>> In Smalltalk, one can drill down through the UI (from menus, windows, etc.) into the actual code, or set a breakpoint launching a debugger on the running system. What other OS (Squeak/Pharo can run on bare metal) lets you do that, all in the same language?!
The same goes for looping and other control structures. This makes any DSL you write a first-class language construct equal to anything else in the language.
I know. What it is not is "clear", for any definition of the term understood by a working programmer who doesn't already know the language and grok the new abstraction.
The point was that this followed immediately an explanation of how much more readable (!) the OO syntax was because there was no separate operator (".") for method invocation. If the former is seriously a criteria for "being better than ruby", the Smalltalk condition trick is an abomination, and immensely inferior.
edit to avoid thread continuation: yet again the response boils down to "it's easy if you know it". So to be clear: 1.) I do know it; and 2.) Duh. But the previous point in the blog post seems to be predicated on the idea that learning the "." operator for method dispatch in ruby is somehow "hard" and that it's an advantage to Smalltalk that it has such a straightforward syntax. Those two opinions cannot logically be held in the same brain.
What it is not is "clear", for any definition of the term understood by a working programmer who doesn't already know the language and grok the new abstraction.
Browse menu, "implementors," select ifTrue:ifFalse:ifMaybe: and find yourself in a short method in under 3 seconds. (Most of that human menu-selection time.) Maybe another 5 seconds for someone familiar with the environment and its conventions to read and understand what they are seeing.
You have a different POV, because it's the POV of someone who doesn't yet know how to fend for yourself in a different environment. Once you learn a few tricks like this, it's very empowering. (And it's not an obscure trick. A seasoned Smalltalker lives by "senders" and "implementers")
Those two opinions cannot logically be held in the same brain.
I don't hold those two opinions. I don't think . is hard, and I don't think Smalltalk syntax is so much easier. What it is, combined with code blocks as literals, is a meta-syntax. I think it's more powerful in some ways.
I think the apparent contradiction is because you're subconsciously imposing your own ideas on the post, and those contradict what he's saying.
1. He didn't say Smalltalk's syntax was learnable — he said it was "readable". He'd probably agree that it's more learnable too, but his actual claim was more like "It's easier to mentally tokenize code that uses spaces to separate elements than code that uses dots." This is similar to how many Rubyists feel that using whitespace instead of parens can make code more readable.
2. He acknowledged that it will be awkward if you're already well-versed in languages that do things differently. But this is tautological. Attacking a programming language for being different from other programming languages is a lot silly.
3. It is true that Smalltalk's pervasive object-orientation will be unfamiliar for people whose experience is limited to Algolish languages, but continuing off 2, that isn't really a bad thing. Smalltalk's model is more consistent than Ruby's. There are basically two things in the whole language: message sends and variable definitions. Your objection here isn't that there's a new abstraction, but that there isn't anything new — it's objects all the way down. It's new to you because you know Ruby, but it's not really a new thing in the course of learning Smalltalk.
I find the lack of a . makes it more visually obvious what you are doing -- sending a message. Maybe something like foo <- doSomething would be more clear, but I always thought foo.doSomething sort of feels backwards, since you are sending a message to foo, not manipulating a property of it.
I know a good iPhone programmer and he credits a lot to learning smalltalk before Objective C to make it a breeze, good to hear from Ruby folks as well! I'm definitely learning it soon!
I found the following particularly useful: 'Smalltalk by Example', by Alex Sharp; 'Smalltalk With Style', by Edward Klimas, Suzanne Skublics and David A Thomas.
This is a great book for beginners in any OO language: 'Smalltalk, Objects, and Design', by Chamond Liu
Also surprisingly useful (terse, but well structured): 'On To Smalltalk', by Patrick Henry Winston
i'm just tired of these front page stories about advising people to learn new languages because of stupid reasons such as "It’s much closer to English that, for instance, Ruby"
There were several other things the author mentioned--though I will admit I found that first part of the first reason somewhat silly.
The thing is, you really ought to expose yourself and at least play around in other languages. No language (except, perhaps, APL, assembly, Forth, Lisp, or Prolog [not that there exists a standard variant of the last two]) is perfect.
Every language does some things really well, other things really poorly, and muddles through the rest. Being familiar with other helps you know when your language of choice might need to call out to something better suited to your problem domain.
We're obviously not far from being able to have SmallTalk-quality interactions with things we build in the browser. Brent Victor's recent talk has spurred a lot of work on more-interactive development environments, some of them in the browser.
I would really like an old SmallTalker to spend some time researching and thinking about the old tools they had: which were valuable, which were more trouble then they were worth? What mistakes did they make that they wish they had done differently? It would be an excellent briefing for the next few years of work on the web.