If you're tired of hearing about the virtues of Smalltalk (like I was at one point) and ask "if it is so good, why isn't it popular?", then watch @deech's talk (Aditya Siram) - "What FP can learn from SmallTalk" - https://www.youtube.com/watch?v=baxtyeFVn3w
I think it is the most accessible explanation of the marvel of Smalltalk, for those who were not lucky to work with it during the late 80-90s.
Also I think Ruby is the mainstream language that is closest to Smalltalk today, with the idea that everything is an object and late-binding as much as possible.
One thing I can't help point out is that Smalltalk / Alan Kay's vision of interconnected objects forming a recursive computing system is not the only "true" vision of OO out there. From Simula thru C++ and then Java and C# also are object-oriented (or class-oriented for those who care about the distinction), but they are statically typed. It is also OO because OO is a word, not a mathematical definition, and when people talk about OO, there is enough similarity between all these variations that we consider all of them to be in the same camp. Plus with the growing move towards strict static typing even in interpreted languages, which I think is driven by actual industry needs and programmer preferences than external marketing, it is becoming a disservice to think of statically typed OO languages as being somehow inferior to the true ideal of object-oriented programming.
Smalltalk prizes interactivity, in the manner that arises from being able to make small, incremental adjustments to code while it (and it's state) remain in memory.
Its rejection of static typing is not axiomatic, merely an expedient way of achieving those interactivity goals. Could the two things be reconciled? I don't know, but I think at least that it shouldn't be unthinkable.
As an aside, static type systems which can be mutated during runtime are astonishingly commonplace. They're very crude, and tend to be called "relational databases", and doing those mutations is a major pain because in spite of all that's elegant about relational algebra, actual SQL is a fucking abomination. (And this is coming from a full-on Postgres fanboy.)
On your comment about the similarity of Ruby, I know what you mean, and yet I regard Ruby as being basically nothing at all like Smalltalk. That's because I'm principally thinking in terms of the development culture, tools, and working practices, and not thinking in terms of the implementation of the VM or the object model, or the names of certain methods.
So similarity between languages is a tricky thing to nail down, not least because in the case of a gestalt system like Smalltalk, "programming language" is actually a tricky thing to nail down.
At the risk of putting readers off by the title, there's a video essay on YouTube called "Object-Oriented Programming is Bad"[1]. It's both thoughtful and thought-provoking, although I don't agree with the conclusion. Steve Naroff (from Stepstone/NeXT/Apple) did a recent-ish set of interviews with the Computer History Museum[2][3] and referenced that video a bit (and extemporized about objects in small parts throughout). Side note: Naroff and Brad Cox are set to present a paper on Objective-C at this year's HOPL[4]. I wish it were as readily available as Allen Wirfs-Brock's JS paper for the same conference[5][6].
Every time you call a method you are breaking encapsulation because you can no longer change the name of the method, it is exposing the internals. Thats why Message Passing has more guarantees with encapsulation.
Abstraction is overdone. Sometimes the simplest implementation is a function. Not a class.
Inheritance is a failed idea of code reuse because it leaves the code brittle.
You can develop GUI apps without OOP - Tcl / tk and some game programming guis are done that way. All that you need are callbacks essentially.
Polymorphism is essentially overloaded functions and you don't need OOP to support that.
Polymorphism is OOP, not every approach to OOP is the same kind of nail.
Classes as concept, are nothing more than extensible modules, and in that regard C and Assembly are pretty much the only mainstream languages that eschew such abstractions.
You can also develop GUIs in Assembly, and I don't miss doing that.
Interesting that you mention Tcl/Tk, given the OOP extensions that were all the rage when version 8.0 came out.
> Classes as concept, are nothing more than extensible modules
If you're talking about ML-style modules, that really can't be farther from the truth, both in theory and how they're used in practice.
Modules can be used (among many other things) to implement abstract data types, which are conceptually a bit easier to compare to objects[0]. Then you'd have to go into structural vs nominal typing, functors vs generics, etc.
You missed the first point I made. C++ / Java break encapsulation by using methods and pretend they are encapsulated.
Julia implements polymorphism without OOP. Modules are better than classes anyways. The whole Java ecosystem tried so hard to bring modules back as components and failed miserably.
If we are going to talk about all types of interfaces then OpenGL is a clear winner. That last time I checked it uses a procedural interface and vertex buffers directly. Why a procedural interface ? Because OOP is incapable of dealing with any complex data structure other than lists in a performant way.
That's exactly why modules are better than classes because they don't have inheritance. It allows for simpler solutions. No debates about taxonomies.
OpengGL is faster. Procedural code is always faster. Global variables are infinitely better than pretending problems vanish with singletons and AbstractFactoryMakerProducer.
I remember going from C++ to Java, what a joke. C++ is infinitely better than Java because it doesn't suffer from OOP monothinking which is beyond pathetic. It was the first time I realised programmers would repeat marketing slogans without verification.
I found OpenGL easy enough as compared to DirectX which is an abomination. Another problem with OOP, it breaks ABI because of name mangling. Had people just stuck to modular programming without inheritance this would have been a non-issue. Namespaces would have become underscores or something.
You can almost backtrack all the horrible decisions in C / C++ and compare it to wirth languages which tried modular programming, bounds checking ....
> Vulkan with its handle model
That sucks. The performance is going to be slow. It's possible they did not go full OOP because of performance.
> OOP based C programming is used all over the place in the Linux kernel
Nope. They implement interfaces / modules using structs. Again, no inheritance and "classes". The most popular example being drivers and filesystem.
OOP doesn't require inheritance, and structs with function pointers are how "classes" get done in C, better brush up your knowledge of OOP, and while you are at it, learn about Vulkan as well.
Also in case you have missed, all proprietary 3D APIs are either OOP or object based.
I wonder where is the OpenGL C implementation that will outperform LibGNMN.
By the way, one of the reasons why OpenCL failed to gain market shared was its focus in C, instead of the nice C++ libraries provided by CUDA.
When Khronos woke up and decided to offer such APIs, it was to late, now we have OpenCL 1.2 renamed as OpenCL 3.0, and SYCL is being re-designed to be backend agnostic.
From a quick read, Vulkan doesn't use inheritance. Its using the C module approach. Even the Web DOM doesn't use inheritance. It seem in the real world no one uses imaginary objects and everyone uses structs.
I think you are finally getting it. Modules ~ Components. Where you and I differ is you think Component = Object. I think the difference is sufficient enough to warrant a complete divorce from the word object.
Linux kernel uses components, not objects.
The ideology of OO is using classes and inheritance to design software. It is an abysmal failure of software engineering, only mediocre managers use OO anymore and pretend visitor pattern is still a thing. All successful OOP projects use components in a disguised form and use a separation between Data (Value Objects, POJOs) and Code (Services). All failed OO projects use classes and take 3 years to deliver even the dumbest of software.
No you are the one not getting it still, components are an area of OOP, usually referred as object based programming.
SELF, BETA and JavaScript don't use classes yet are OOP.
VB originally did not do inheritance and yet it did provide another OOP approach.
Plenty of other languages can be looked upon on SIGPLAN.
Speaking of failed OOP projects, Web DOM, Android, iOS, CUDA, DirectX, LibNMN, LLVM, Metal are indeed such a colossal failure, what were they thinking.
In case you are lacking CS literature I can give you some hints.
Modularity is the very fabric of most engineering disciplines. As opposed to that, OO is a holistic "ideology" about using classes and inheritance to design software. I call it an ideology because despite its abysmal failures people still refer to it in positive terms.
Apart from Android not one software from the list uses inheritance and classes. OO has shown a narrow success in GUI.
In C you don't have modules and interfaces, so what you do is define a struct with pointers. Now you can compile any .c file which follows this interface and dynamically load it into the software.
Python / Perl / Javascript / Ruby ... support this. Remember how much code is resused in the packages downloaded when you do pip install ? Thank modules for that. Not OO. Because of duck typing these dynamic languages don't need interfaces but you can find code snippets that implement it with keywords like pass.
In modular coding you get libraries, extensions and plugins. I find it sad not many people use these terms and prefer to honk OO every time.
Ruby is a joy to use and relatively close to Smalltalk in many many ways.
I wish Ruby had taken Python's spot. When Rails exploded ~2006, I thought it'd become a mainstream language. But sadly it has never been very popular for non-web things, if we exclude Japan.
One reason is probably that the standard Ruby implementation (MRI) was really slow till recently. Smalltalk, on the other hand, had extremely good VMs that served as embryo for the JVM.
I've used Ruby for many big projects (but never used Rails!) and it has scaled really well for large and exotic things such as abstract interpreters.
Speaking of Ruby, there is this book that I read a few years ago (five years ago, in fact – time flies), that was using Ruby when explaining the things it was talking about.
Personally I don’t use Ruby and prefer Python instead, but the book was very enjoyable nonetheless so I would recommend that book to anyone, even to people like me who don’t really like Ruby in general and don’t really want to read or write Ruby in general.
Stuart, T., 2013. Understanding Computation: From Simple Machines To Impossible Programs. O’Reilly.
Another good "non-rails" Ruby book is "Enterprise Integration with Ruby"[0]. Unfortunately, it's a bit dated (2006), so I am sure some of what Schmidt details is no longer supported/valid. Still, a cool book IMHO.
I didn't give Ruby a second thought after hearing Matz say something along the lines of being a bit sad that people were using it because it meant that he couldn't change it anymore. It was his toy language that escaped his control and now he had to worry about compatability and couldn't just break things. It's not a good sign when the creator didn't want it to be used that much.
I'd be much happier if someone could instead just provide a version of Smalltalk that everyone can agree on.
"Use Squeak!"
"No, Squeak is old! Use Pharo!"
"Pharo doesn't adhere to the Smalltalk standard. Just use gnu-smalltalk in a terminal!"
Never have I seen such a self-defeating community. If the Smalltalk community wants it to be anything more than a historical curiosity, I beg it to form some kind of standards committee and agree on a common implementation so that I can learn Smalltalk without worrying that I'm studying a dialect that is not mutually intelligible to the other implementations.
Gilad Bracha gave an interesting talk (or in his words, "[maybe] the best talk I ever gave") called "Utopia and Dystopia: Smalltalk And The Wider World", where he posits a universe where the Smalltalk community has recognized and proactively fixed this problem, along with some other problems that outsiders see when they look at Smalltalk.
His blog is also great to follow as a general programming blog, and as it turns out, he wrote a post just two weeks ago where he rehashes some of the content.
The Smalltalk community is an artifact of the pre-Internet days. See Forth or Lisp for the same result. Communication was slow, in the form of publications and you couldn't get your hands on actual code (which probably wouldn't run on any of your machines anyway).
See the many Unix clones before Linux. The difference is that Linux came along when you had GNU code to avoid having to implement ls, ps, etc yourself, you had many people with 386 PCs and you had the Internet to work together without having to be all in the same room (not to mention not having to set up a company to sell CD-ROMs, though other people did that for Linux).
By the time languages like Python and Ruby came along it was a different world and they could be more Linux-like in terms of community and less QNX/Coherent/Idris/BSD/Irix/AIX/Solaris/...
Putting a splintered community back together is not an easy task.
Note that Squeak, Pharo and Cuis deviate from the ANSI Smalltalk standard in the same ways (Traits, {....} syntax for runtime collections).
The Forth situation is a little bit different: it is a language designed to be easily to implement, so everyone is redoing Forth all the time, including its own creator (Cf. Colorforth) who said that "Forth is what Forth programmers do" [1].
At the same time Forth has had an unofficial standard as soon as 1979 (Forth-79 followed by Forth-83) before the official ANSI standard (1994).
Actually, a splintered community is not an entirely bad sign. It means that there is no monopoly and that the sub-communities are wealthy enough that they don't need to make compromises with their siblings in order to survive.
Ah, you mean like a version of Python that everyone can agree on!
Joking aside, it's an entirely understandable sentiment, but Smalltalk is not only an old language, but also one that lives in a symbiotic relationship with its tools (which defy the normal notions of language standardisation).
As things stand, if you want a standard, what you're likely to get is a time-capsule. Pharo in particular does not want to be a time-capsule, and while it's certainly been a source of frustration to me that Pharo has existed in such a state of flux for so much of its life, I understand that the change is necessary, and I remain cautiously hopefuly about the direction they're taking.
I'm not a daily user of Pharo, so while I have a rough idea that it is becomming more settled as time passes, I'm not an authority here.
I had a lot of the same issues and finally started to enjoy using smalltalk once I just gave up on the idea I was going to use it for anything practical. After that I found squeak to be just fine to play around with.
From my perspective as someone learning about it post 2015 is that the really killer “feature” is the ability to modify anything anywhere while the image is running. But this is also the feature that makes it so impractical. You start to realize as you are tinkering how simple and elegant it is and how much modern tooling really gets in the way. But this is all based on it being built up upon itself and all the magic of this sits in an environment that’s so foreign to other tools it always feels awkward to interface with them.
I really like all of Sandi Metz's talks and books on Ruby for that reason. Her Smalltalk background really shines through to bring out the best parts of OO, and are really applicable for just getting better at design and architecture.
OO was the best programming paradigm until people recognized the power of concurrency. Even in the usecase of GUI programming, where OO is supposed to shine the brightest, OO is a failure because interactive programs are extremely concurrent. Even back then when everything was executed in serial GUI frameworks were designed concurrently in crummy languages never designed to support concurrent programming such as C. Or worse, C++.
And functional programming is no good as a general programming paradigm because:
1. Little of computing--almost nothing--is declarative. That means functional programming's non-general by definition.
2. Programming cannot be married to mathematics despite what formal proof proponents and people who think naming their language "Pascal" is a good idea think. It will always be an arranged and sham marriage.
3. Thinking being able to easily execute your declarative programs in parallel means you'll never have to think concurrently and can just outsource everything to Hadoop only means you can't understand the difference between parallelism and concurrency.
No, it depends on what you're doing. Always does, always will.
> Even in ... GUI programming, ... OO is a failure because interactive programs are extremely concurrent
Seems to work well for me on windows. What's the problem precisely?
> And functional programming is no good as a general programming paradigm because ... Little of computing--almost nothing--is declarative
That's just wrong.
> Programming cannot be married to mathematics...
You give no evidence despite it being a long association.
> Thinking being able to easily execute your declarative programs in parallel means you'll never have to think concurrently
Yes, because concurrency only becomes an obvious issue when state is involved. So FP sidesteps that by not having interacting state. I have some criticisms of FP but this is plain silly.
> Little of computing--almost nothing--is declarative... That's just wrong.
* Artificial general intelligence
* Operating systems
* Video games
* Emulators for hardware
* Interpreters
* Debuggers
* Word editors
* Image editors
* Graphical user interfaces
* Robotics
* Web browsers
* Servers
Basically everything that makes computing interesting is non-declarative and concurrent. Financial math on K street, parser combinators, and SQL queries are the declarative segment of programming.
Declarative/imperative are models, not necessarily implementations (although they often are treated as model x = implementation x). You need to separate the two conceptually, but in implementation you can do both. Anything you can do declaratively you can do imperatively and the reverse.
As such it makes it meaningless to say that almost nothing is declarative because how you choose to create it is a choice. How well it runs is another matter because real hardware is relentlessly state-y, but that's an implementation issue. And that's fine, and sometimes imperative stuff is just cleaner.
But you can write a web browser or a GUI or whatever declaratively, but underneath it will be imperative because that's hardware.
Declarative vs imperative is a choice, not necessarily a 'natural' thing, (depending on the problem, I'd say a web page renderer is distinctly stateless - take some static HTNL, render it, where's the state?). A web server can be stateless too, a request comes in, a web page goes out. I need someone else to speak for others, pretty sure stateless GUIs have been written.
Any big data cruncher that works on petabytes, purely with output coming from input deterministically is effectively stateless.
Nothing is declarative or imperative outside of a certain implementation of a solution. All of the things named trivially have declarative solutions because of Turing completeness. Whether or not a paradigm lends itself easily to something is a bit of a different question, but I think a lot of people tend to say “oh, that’s obviously stateful and imperative” merely because they haven’t thought about the problem in a different way.
Turing machines only model mathematical functions. They cannot model anything on my list. That's why computer scientists invented I/O automata in an attempt to build a theoretical model that handles some of those items on my list.
> “oh, that’s obviously stateful and imperative” merely because they haven’t thought about the problem in a different way.
It doesn't need to because it's implementation details.
Where it's needed such as in modelling the very important implementation detail of parallelism on multi-core machines to ensure correctness (such as with model checkers like Spin) then stuff like buchi automata are used, but that's dragging maths into the real world to solve real world problems. Turing machines don't live in the real world.
We know a Turing machine can't model all aspects of concurrency because a Turing machine with threads can compute an integer of unbounded size while there's always a bound on the greatest integer an unthreaded Turing machine can.
But this is all naval-gazing anyway. What's even the point of a purely-declarative OS when it's either gonna:
1. Act as a glorified C preprocessor for an imperative language like Haskell and its do-notation?
Haskell with do-notation is not imperative, that’s a common misconception. It’s a special syntax for working within a monad that desugars to nested function calls.
Typically declarative systems are interesting because it is easier to prove strong properties about them.
I agree. Declarative systems are interesting. I am not against studying, implementing, or understanding declarative OSes from an intellectual viewpoint. Rather, people generally speaking ignore that the declarative perspective is not teleological and doesn't reflect the teleology of an underlying OS.
Imperative programs are so popular among "joe schmoe" average programmers because they have a clear teleology. People are willing to forgive that imperative programs are harder to formally reason about because they make the teleology clearer. But have you seen declarative code? Because it's like math formulas, each function needs the same kind of documentation in order to understand the teleology behind the function.
OO has had most success in GUI programming. As for concurrency, Erlang seems to do ok and its creator called it "possibly the only object-oriented language"
> Even in the usecase of GUI programming, where OO is supposed to shine the brightest, OO is a failure because interactive programs are extremely concurrent. Even back then when everything was executed in serial GUI frameworks were designed concurrently in crummy languages never designed to support concurrent programming such as C. Or worse, C++.
I must say that I have trouble reconciling this with the fact that every single GUI program running on my computer right now is written mostly in C++ with a bit in C for my WM and a bit of Rust for Firefox.
I think it is the most accessible explanation of the marvel of Smalltalk, for those who were not lucky to work with it during the late 80-90s.
Also I think Ruby is the mainstream language that is closest to Smalltalk today, with the idea that everything is an object and late-binding as much as possible.
One thing I can't help point out is that Smalltalk / Alan Kay's vision of interconnected objects forming a recursive computing system is not the only "true" vision of OO out there. From Simula thru C++ and then Java and C# also are object-oriented (or class-oriented for those who care about the distinction), but they are statically typed. It is also OO because OO is a word, not a mathematical definition, and when people talk about OO, there is enough similarity between all these variations that we consider all of them to be in the same camp. Plus with the growing move towards strict static typing even in interpreted languages, which I think is driven by actual industry needs and programmer preferences than external marketing, it is becoming a disservice to think of statically typed OO languages as being somehow inferior to the true ideal of object-oriented programming.