1. 17

  2. 4

    “Smalltalk is powerful because all Smalltalk data are programs–all information is embodied by running, living objects. Class programming in Smalltalk is simply data-manipulating programs that are themselves data–it’s the inverse of the Lisp philosophy, but the end result is the same. It’s what enables the Smalltalk debugger to freeze, dissect, modify, and resume programs mid-execution.”

    At least this part seems true of the LISP machines and environments that keep the program live in the background for modification. Everything being objects is different from LISP but editing a live environment is something a LISP can do.

    “It’s what enables the browser to instantly find all objects that respond to a given message, or all superclasses and subclasses of a given object, or every running instance of a given class.”

    That part might come from, based on descriptions I’ve read, Smalltalk being more limited than LISP in terms of not having macros that change the language too much. Limiting the power at the syntax level makes automated analyses by IDE’s more powerful and easy. Python’s One Way to Do It has similar effect versus Perl that tries to be all-powerful (and harder to understand/parse code) like LISP. Just my guess based on what Smalltalk articles and users say. I’m still not able to commit to learning it all first-hand since I’d have to learn more than just Smalltalk (proper OOP for one).

    1. 4

      I think the most interesting aspect of macros is that they allow keeping the core language small and focused. One problem many languages have is that they accumulate too many features over time. You have languages like C++, Java, Scala, and JavaScript that have too many things happening. Nobody knows the entire language at that point, and people start writing “the good parts books” for them.

      The fundamental problem is that these languages not easily extensible via user space libraries. Any time you need a feature, it has to be added to the core language by the language maintainers. As development practices change features that seem to be a good idea at one point often become anti-patterns later on. However, since they were already baked into the language, you can’t get rid of them, and so the bloat grows.

      Meanwhile, Lisps can side step this problem because ideas can be expressed via libraries. For example, Clojure has been around for a decade now, but there have been very few changes in the core language. Most of the ideas have been explored in user space.

      Go came out after Clojure, and it had a cool idea around communicating sequential processes. This is a core feature of Go, and baked into the language. Clojure developers liked this idea and created core.async that mimics Go channels. The language didn’t need to be modified in any way to support this. Perhaps, in a decade we’ll decide this wasn’t a good idea, or find a better way to do this. The core.async library will become deprecated, and projects using it will have cruft in them. However, the language itself will not have this cruft, and new projects and people learning it will not have to know about it.

      That is the fundamental power of homoiconicity in Lisp that has not been matched by any mainstream languages.

      1. 7

        I think the most powerful example I’ve seen of extension you describe is how Common LISP got its object system (CLOS) by just adding it as a library. Compare that to the work that went into C++, Java, C#, and so on. I remember thinking, “They just added a library? And if they wanted Aspect-Oriented Programming, they just added a library for it? And if they wanted logic programming, they just embedded a Prolog that can call native functions for things Prolog doesn’t handle easily? They just throw it in there without building a new toolchain?”

        Pretty jaw dropping to see that power coming from imperative languages such as BASIC and C. The primitives of little Lisp’s were also small with interpreters easy to write. I knew such tech was ahead of what I was using by leaps and bounds. The market knew otherwise. ;)

        1. 3

          You have languages like C++, Java, Scala, and JavaScript that have too many things happening. Nobody knows the entire language at that point, and people start writing “the good parts books” for them.

          With Lisp and Smalltalk, you just push the problem around: Nobody knows all the libraries. If something like an object system is standardized by the language, it is at least the same for everybody. How do you compose libraries, if they happen to use different object systems? Reminds me of strings in C++.

          Btw, isn’t Scala in the Lisp and Smalltalk camp? I heard it is actually a small language, where libraries can do magical things.

          1. 4

            FWIW I work with Clojure professionally, and I don’t see the problem with libraries. The community settles on a set of libraries that are popular and that’s what gets used. With regards to Scala, while it’s true that it allows doing magical things via libraries, it’s a huge language by design. I’d say it’s antithesis of Lisp and Smalltalk.

        2. 3

          I feel there are two (obviously this is a huge generalisation and a false dichotomy) different ways to look at programming, with different models of programming languages. Summarising my two ways of thinking post, you either look for a language that exposes one concept that you can understand and cast all of your problems to, or you look for a language that exposes lots of different concepts and take an a-la-carte approach where you fit the language feature to the problem.

          I don’t think either is “the right way”, but I do think that I look at things the first way. I, similarly to this author, think of Lisp and Smalltalk as very similar as a result:

          The Lazy Evaluator loves Ruby because Everything Is An Object (and they love Io more because in Ruby there are also classes). The Lazy Evaluator is delighted to know that in Lisp, Everything Is A List.

          However I think that this author could have looked past Smalltalk to Self. In Smalltalk, everything is a message or it is a class or it is an object (and yes, classes are objects, but classes are also special). In Self, everything is an object or it is a slot, so it’s even easier than Smalltalk.

          1. 1

            An interesting observation, but I think language mavens vs. tool mavens is closer to what I see in real life.

          2. 1

            I think we should remember that the whole point is less about a particular language but rather about homoiconicity.

            In systems where means for abstraction is the basis of themselves, abstraction becomes a no-op

            My point is there is no need to stop with this at a mere computer language when we have every opportunity to go deeper