Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Lower syntactic and semantic overhead, pretty much all of the language semantics are built from two properties/behaviors (and hooks into the interpreter): blocks and sending messages.

Sending messages are method calls, the difference is mostly contextual. Blocks are first-class functions with closures and nonlocal returns. That part's important when you're trying to implement e.g. loops (otherwise you have to add flags or throw exceptions, as in Javascript).

In Smalltalk, iteration is a message and a block:

    aCollection do: [item|
        "process item"
    ]
but that's not exactly rare these days. On the other hand, a conditional is a message and two blocks:

    aBoolean ifTrue: [ "code if true" ] ifFalse: [ "code if false" ]
A repeat loop is a message to a block on a block:

    [ "dynamic condition" ] whileTrue: [ "repeat while true" ]
and so's a try/finally:

    [ "a piece of code which may blow up" ] ensure: [
        "error recovery code" ]
or a try/catch:

    [ "a piece of code which may blow up]
        on: SomeError
        do: [ :sig| "error handling" ]
What this means is that there are very few special cases in the language, and the user of the language has the same power of expression as the designer of the language (much as in Lisps or Forths), the only limit is the hooks into the runtime but that's about it.

Also, message cascading is a minor but way cool (and pretty much unique) feature of Smalltalk, it lets you have your cake (return interesting values from methods) and eat it too (chain calls):

    someObject
        aMessage
      ; anOtherMessage
      ; yetAnOther
      ; andOneMore
will send all 4 messages to the same `someObject` no matter what the previous message returns.

That tells you what the language's priorities are.



Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: