Hacker News new | past | comments | ask | show | jobs | submit login
I can read C++ and Java but I can’t read Smalltalk (2000) [pdf] (sdsu.edu)
110 points by tjalfi on Dec 18, 2021 | hide | past | favorite | 190 comments



Smalltalk is IMO super readable, it's just not familiar or standard. To me, unreadable languages are languages that rely heavily on symbols. The obvious extremes would be perl or APL. In those, if you don't already know the symbol it's pretty much impossible to figure out. In smalltalk, it tends to read like english so you can usually understand what it's doing even if you're not entirely familiar with the syntax.

To be honest, I find this is actually the hardest thing I grapple with when I look at mathematics that I'm not familiar with. A lot of times the concept and the equation are simple, but if I'm not familiar with what a specific greek letter is supposed to represent it's completely impenetrable. Not that I'm saying we have to change math, but I always found that was the biggest obstacle for me.


Yup, symbols are the hardest.

A few years ago (on sort of a whim?) I read a ML science paper without first having much of the foundational knowledge; I'd end up having to go off on more than a few Google dives per paragraph, just to understand what they were talking about.

But you can't Google an equation, or a symbol in an equation - at least I couldn't, and get meaningful results.


The biggest advantage computer scientists have over mathematicians is that our variables can be more than one character


Not in academic papers unfortunately... And while math symbols are somewhat standard across papers, every CS paper comes up with their own meanings for half the symbols they use.

Sometimes they are nice enough to say "we use random squiggly arrow to mean x", but then you need to keep a table of symbols on the side to even read the paper.

Other times they just reuse "common" symbols and expect you to know, even though that symbol has been used for more than one purpose over time.

It's all very tiresome.


Mathematicians allow multi-character identifiers when it comes to functions, though. sin, abs, det, etc.


But those are not variables.


> I read a ML science paper without first having much of the foundational knowledge; I'd end up having to go off on more than a few Google dives per paragraph, just to understand what they were talking about.

That's pretty much the norm with scientific publications, no? They're intended to be read by people with advanced degrees in the field.


You know you have a problem when even advanced degrees in a close field isn't enough, because your symbols are different. (And yeah, ML has this one.)

We should have iconographic dictionaries for Math.


One man's i is another man's j.


> To me, unreadable languages are languages that rely heavily on symbols.

Interestingly, the first Smalltalk, Smalltalk-72, used loads of symbols.[0] Introducing a new variable used an index finger symbol. Evaluating a message used an opened eyeball. The "turtle" was represented by something looking like a smiley face. There's a working emulator of Smalltalk-72 on Dan Ingalls' website, and I'd recommend playing around with it.[1] They really embraced the "everything is messages" thing, and couldn't figure out how to optimize it on their hardware (since the language is frankly way too powerful and not amenable to static analysis). If they could have seen the utility of something like a JIT, the future might have turned out differently, but as it happens, the Smalltalk variant Self was the first highly-efficient one, almost 20 years after Smalltalk-72.

Sun later cannibalized the Self team to have them focus on Java performance, and the result was the HotSpot VM, which in some ways saved Java from being a failure.

[0] http://www.esug.org/data/HistoricalDocuments/Smalltalk72/Sma...

[1] https://lively-web.org/users/Dan/ALTO-Smalltalk-72.html


afaik Smalltalk-80 was the language that gave rise to implementations that were available outside the lab.

Smalltalk-80 was the language IBM trained their consultants to use.


There was one Smalltalk-72 inspired implementation not created by PARC. It was based on their publications before Smalltalk-80 was released. Rosetta Smalltalk


afaict That was a “prototype”. Was it ever made available to anyone beyond the authors?


It was supposed to be released to run on Z80 machines. Apparently it was killed when Smalltalk-80 was starting to be released (if Ted Nelson is to be believed):

https://archive.org/details/RosettaBrochure/RosettaBrochure/...


They wrote: Rosetta Smalltalk was shown at the Exidy booth at NCC'81 and beta-tested at about 40 sites across the country.

But it was unfortunatelly discarded as soon as Xerox published Smalltalk-80.


Fair enough, I don't wish to diminish their work, or lionize Smalltalk-72 over Smalltalk-80.


Page numbers on the first citation?


Page 16 for the PDF, actual page # is 9. It shows up earlier but that's the best early example of the little face representing the turtle.


> Smalltalk is IMO super readable

Yep, definitely one of the most readable out there.

> unreadable languages are languages that rely heavily on symbols.

Yes and no.

I actually find symbols useful for very common and mostly structural elements. As an extreme example, assignment as '←' or ':=' or '=' is much better than "assign to" or having to use special accessor methods/messages (leaving aside that these things should be dynamic).

And I actually like the way that Objective-C uses "-" to introduce instance methods, because they are so common and there is really not much else that could go there, except maybe a class method introduced via "+". Having to write "function" or "func" each time is just clutter, and non-sensical clutter because there is very little else that could go there, and certainly nothing user defined last I checked. C of course doesn't use anything at all, you just start writing the function return type and name.

Similar with "set" and "get" for property accessors in C#. Those just seem wrong at that location, though I don't really have a good alternative. I tried to use "=|" and "|=" in Objective-S (http://objective.st), but nope, not a good alternative. Although "|=" is pretty good for dataflow constraints / permanent assignments.

Similar with "at:" for indexed access in Smalltalk. While I appreciate the uniformity, the "[]" syntax really adds something here and is common enough for special syntax to make sense.

So anyway: names for semantic-bearing and user-defined constructs. Symbols for very common structural/architectural elements, where they can be made to make sense.

UPDATE: In many ways, this is a lot like natural language does it, though of course not identical. It would be awkward to have to write "full stop" or "this sentence ends here" at the end of every sentence. So: punctuation.


I had the same problem in graduate school until I realized that Smalltalk is not designed to be read outside it's IDE.

Most of the problems with that language, rightfully flagged in this article, are not as problematic when the code is read inside it's native environement.


This seems like one of those spots where Smalltalk is a victim of cultural changes that happened around it.

25 years ago, a tight integration between the language and the IDE like that would have sounded great to me. Nowadays, though, it strikes me as a terrible, terrible flaw.

What's changed is the development of a collaborative development across the Internet, and a stronger emphasis on code review. So now, for a great many projects, the most important code reading typically happens outside the code's native environment. It's done in whatever least-common-denominator view you get in your team's code review tool.


With such powerful computers and networks now, is there really any excuse for the least common denominator view on your team to be bad?

The terrible flaw, to me, sounds like it's the workflow that won't bother installing the right tools for code review. It's not like you're stuck with printouts or something where those tools aren't practical.

(If the IDEs or editors are lacking things needed for code review, then that's a problem, but it's not a problem inherent to the idea of tight integration.)


How would GitHub or Bitbucket go about "installing" Microsoft's or Apple's proprietary tools on their website?


On Microsoft Github, in a repository such as https://github.com/nodejs/node press `.` (the full stop key) and it will take you away to github.dev, load Microsoft's VS Code in-browser to view and edit code with VS Code plugins and highlighting.

And from there you can use GitHub Codespace to "develop in a cloud-hosted, customizable environment" to run and debug.


And you can't even hit the back button. Incredible.


Apologies, I just read my comment again...

To be clear, I'm talking about the VSCode app. Once you visit it they hijack the browser history and hitting back causes the entire app to reload, over and over again, until you manually drop down the history menu and jump 2+ pages back.

I realize now my comment sounded rude and pointed toward the parent (not at all the intent) - I can't edit it so here I am again.


hit it twice. is that the point? def not, but i got it to go back


Perhaps I wasn't fast enough, but it didn't work for me.


They can do their primary directive to act as public centralized vcs repositories.

The proposition here is that the IDE provides dev process tooling so you are in fact collaborating with your team, e.g. reviewing your code, but Github (Microsoft) and other centralized services are not necessary and not included in the activity. And yes, if AWS etc goes down, your IDEs will continue to work and you can continue to collaborate.


GitHub == Microsoft and has been for a while.


It is funny, one of the things that has bothered me for quite a while is that diffs don’t understand code.

For example if I add an additional usage to a global variable to a file, while someone else renames it in other files, git happily merges with no conflict.

Tighter language integration can help with that.


This tight integration between language and general purpose tool is a nice idea with a terrible price. It would make tools a lot harder to develop and they would be a lot slower as they now have to perform significantly more work.


That strikes me as outside the scope of a feasible version control tool (and is probably undecidable in most cases). Seems like you’d be much better off handling that with a test suite and CI.


I kind of agree, but if you have a very tight coupling, you could version control objects of the language and not text files. For example, a function could be versioned as a function, not a chunk of text.

For example, I have seen cases with diffing where based on whatever algorithm, a very small logical change, (like moving a function up or down in the file along with a minor edit), creates a very confusing side by side diff based on whatever similar lines it think match up.


It can, but like with other “rich” structures (type systems, data schemas, IDLs...) there is usually no single good solution, and when you need different ones to interoperate (either because you hit the limits of one of them or because you need to bridge two preexisting systems) you need to write a lot of tedious boilerplate at best and are completely stuck at worst. AFAICS that’s why amorphous sequences of bytes won as the fundamental (absence of an) abstraction in many places (files, networks, RAM, etc.).

I would very much like for this not to be true, but there doesn’t seem to be a good solution.

With syntax trees in particular, it’s also frequently difficult to find even a single good option for what you would reasonably want a diff to be: last I checked rich-text diffs usable over arbitrary HTML (even sans CSS) still sucked in half the cases you’d want. Line- and word-based diffs over the source also suck, naturally, but at least they do so uniformly. It’s not an accident Stack Overflow will usually try to show you a rich-text diff when editing but will occasionally fall back to word-diffing the Markdown.

And a version control system needs to interoperate above all. Unlike, say, an IDE, and you do see attempts at semantic and even structured editing in IDEs.

/me continues to fantasize about interbreeding Paredit and Pijul one day


There's automated testing in a ci/cd pipeline to catch that, I suppose...


Git allows you to use a custom diff tool for a specific file format. The problem is that these centralized source hosting/review tools only let you do about half of what Git can do.


you can write a diff tool that talks to an LSP server


> This seems like one of those spots where Smalltalk is a victim of cultural changes that happened around it...25 years ago, a tight integration between the language and the IDE like that would have sounded great to me.

Smalltalk has always went in the amazing language to look for inspiration from. Commercial implementations were pretty pricey (I think in the thousands). Ultimately, smalltalk really fell out of favor because:

* Bad story on concurrency and multiprocessing.

* Wasn't really all that portable.

* Tightly bound with development environment.

* Resource hungry mostly due to being tightly bound to the ide, and many implementations required the IDE to ship with the product.

* Expensive

I learned a lot about object oriented development from playing with smalltalk, and was able to employ a lot of what I learned using Java, Python, C#, Objective C, and C++. To this day, you really see a lot of code editing and management concepts that started in smalltalk in your favorite IDE.


> * Bad story on concurrency and multiprocessing.

Mostly non-premptive lightweight concurrency (with the multiprocessor exception Actra)

> * Wasn't really all that portable.

iirc Just copying files from MacOS to MSWin to Unices was enough to port software.

> * Tightly bound with development environment.

That was considered to be a feature not a bug.

> Resource hungry mostly due to being tightly bound to the ide, and many implementations required the IDE to ship with the product.

The IDE could be stripped-out.

> * Expensive

Everything is expensive when the alternative is free-as-in-beer.

> Ultimately, smalltalk really fell out of favor because:

"The Rise and Fall of Commercial Smalltalk (2020)"

https://news.ycombinator.com/item?id=29223880


I don't really understand this perspective, I remember using Smalltalk VisualWorks back in 2005 and it didn't even have syntax highlighting. I'm unclear why an IDE is more needed than another language. If anything java and c++ are way more IDE dependent because it's hard to know what parameters mean by their position, whereas in smalltalk they're named.


The IDE presents code in context — a method source is presented within the context of a class; a class source is presented within the context of superclass and sublcasses.

And then the fun starts —

https://www.researchgate.net/publication/3422160_Tools_for_m...

"Tools for making impossible changes - experiences with a tool for transforming large Smalltalk programs"


Let me add a classic "tutorial":

t.rotate (a, v); // Original

t rotate (a, v); // Who needs dot?

t rotate a, v; // Who needs brackets?

t rotate by: a around: v; // Who needs ambiguity?

t rotateBy: a around: v // This is Smalltalk


That's literally from page 2 of this, you could at least state that you're quoting the document.

Also, you missed a step. Before "ambiguity":

  t rotate by a around v; //Who needs commas?


  t.rotate(a, v);
  ...
  t rotateBy: a around: v
I will consider only first and last as the rest is just fluffing around.

Objectively speaking (yeah right) there is no difference and both serve the same purpose. For whatever reason the first form is more visually and mentally pleasing to me.

If it was written by me it would be:

  t.rotate(angle, around);
would also have something more meaningful instead of t unless the scope is very small.


Why not compare it with t.rotate(rotateBy, around)? Could a,v used for many purposes and this example allows us to indicate their role for this specific call?


Because a and v would be more typical variable names than rotateBy and around. Note that the author did not change the variable names in the translation process, they left them alone. So you could drop any variable in there but the calling of rotate becomes clearer (subjective) by switching to keywords and no longer relies on programmer discipline to have good variable names.

And yes, they probably could be used for other purposes. The names are mnemonics for "angle" (a) and "vector" (v). How you arrive at them and what you'd use them for could easily vary across a system.


Because those are names the caller decided upon, so they can just as easily misinform the reader as correctly educate them. The caller could have mistyped the call as

     t.rotate(around, rotateBy)
and the error in the effect might seem very mysterious indeed. The beauty of keyword args is that the mapping of caller's name to function argument name is explicit, and therefore reads correctly or incorrectly immediately at the callsite

     t rotateBy: point around:degrees
is obviously an error, without sending the reader to look up the definition.

Compiler-enforced clarity rather than relying on every individual piece of client code to always name things well & never make a mistake.


[t rotateBy: a around: v] // This is Objective-C

I’ve never seen Smalltalk before, but I did find the verbose syntax of ObjC had some benefits.

That being said, typical C programmers don’t add all that whitespace, so the “who needs dots” and stuff is a bit misleading.


Okay, now do something that's fairly readable in non-smalltalk syntax:

t.rotate(a, v).translate(x, y).scale(w, h);

A better way to remove all the "who needs X" is s-expressions. At least then you are left with something that composes a little bit.


In Toit, which is in some ways a Smalltalk dialect that would be:

t.rotate a v

Alternatively if the rotate method uses named args:

t.rotate --by=a --around=v

(See toitlang.org).


Snippets like this:

    account deposit: 100 dollars.
are why I love Smalltalk (and its followers, e.g. Ruby). So much expressiveness, reading like a sentence. And Smalltalk even had the ingenuity to use period as a statement terminator, so it feels even more like a descriptive sentence describing the domain concept.


Rebol takes things further by identifying $ as a datatype.

    account/deposit $100
Nobody cares about rebol but I always bring it up in terms of expressivity.


Yeah, I have no idea why Rebol and Red aren't more popular. ( https://www.red-lang.org/ ) They pack such a bang for the buck it's almost embarrassing for other language/runtimes.


Rebol itself is practically dead, no new release in a decade. It was also proprietary early on and a "weird" language (interesting, and good, but non-standard in so many ways that it was very niche). That killed its potential in the late 90s and early 00s when everyone was moving to open source scripting languages that filled the same niche, but with more conventional syntaxes and free access.

That's why it isn't more popular. In some ways it was a few years too early (to hit the zeitgeist around DSLs), but it was also a few years too late for its proprietary model.


And something else that needs to be said specifically about the Red programming language. I like the full-stack concept, ease of use, cross-compiling, and the goals they are shooting for. But, the lead developers need to get it moving. Like a small fire needs to be lit under the butt, as the competition isn't standing still.

The last stable release has been stuck at 0.6.4 since 2018. I know the lead developers have recent automated builds (December 2021), but come on, such is not going to inspire faith in casuals to join the bandwagon nor keep getting mentioned by the media. Many users like to see newer stable releases, until the project achieves its stated goals. A lot is to be said for maintaining momentum and enthusiasm.

That's another aspect of the hurdles for the newer programming languages, it's harder than ever to keep people's attention and whip up excitement.


The problem is that there are so many new languages that it's hard for any of them to gain enough momentum to encourage enough programmers or businesses to learn or even look at them. Not to mention that various top 10 languages are supported by huge companies that may rather snuff out or at least throw shade on up and coming languages that threaten their interests.

The development pace of many of the new languages is relatively slow, despite having some great ideas, syntax, or features. Which means years before they have a large enough ecosystem and libraries, to even come near to mounting a challenge to the more established languages.

For instance, another new one out there that I like is VLang (https://github.com/vlang/v). Like Red, it needs to find a sweet spot that will propel it to greater usage and recognition. Partly that can be cross-compiling and cross-platform application development. Also, strong emphasis on mobile development for both Android and iOS would help, but Apple makes their part of it difficult. To stand out, it means having easy to create UIs, their own IDEs (to maximize language features), updated documentation (to help beginners), books about it, etc... Just being on Visual Studio Code, with a hundred other languages, makes it hard to get noticed.

Compare Red with established heavyweights like C#, Python, JavaScript, or even contenders like Delphi/Object Pascal. Not so easy to pull attention away from those languages and the thousands of projects using them, unless something very compelling can be shown or proven.


> Yeah, I have no idea why Rebol and Red aren't more popular

Rebol died (for all intents and purposes) because it stayed proprietary without a large enough proprietary market too long, and good enough open source languages took the niches it could have had and built out robust ecosystems that it never developed.

Red has been disadvantaged by the ecosystem consideration, and hasn't found a killer focus that gets people over that in enough mass. They tried chasing crypto for that...


julia can do things sort of like this because it has juxtaposition = 'implicit multiplication'

julia's parser (which is written in scheme!): https://github.com/JuliaLang/julia/blob/master/src/julia-par...


Similarly, TeX bakes units into its syntax, but METAFONT (which is much more pleasant as a programming language in general) just has a production for <numeric token> <numeric variable> instead (yes, it has a very involved context-dependent grammar), though it gives up type checking because of that.


Just took a quick look at Rebol and it looks interesting! I love languages that push the boundary of what they allow programs to "naturally" express


> Rebol takes things further by identifying $ as a datatype.

Well, money! is a datatype, $ is a sigil that identifies a money! literal.


Which is the better choice these days, Rebol or Red?


Rebol, is mostly "dead", and I don't like to so easily throw the term around. But, originally it started out as a proprietary commercial language, then when it couldn't make enough money, went open source. It has some good concepts, and passionate followers, but didn't go mainstream. Even though it went open source, in the flood of so many languages that exists now, continual development stalled. However, it did produce several offshoot descendant languages.

Something to point out, is there is a lot of old tutorials and information on Rebol that becomes more useful as references, if a person learns any of the descendant languages.

Red (https://www.red-lang.org), is a very good open source offshoot. If a person is choosing between them, I think most would recommend it. But, the problem with Red is its development can be described as sluggish. The lead developers appear overly preoccupied with other projects, as oppose to getting Red into a more useful state and delivering on the stated goals and expected features.

For example, one of its main benefits is easy cross-compiling to other OSes. However, it's stuck in 32-bit, and needs to have a 64-bit version to keep pace with the requirements of macOS, iOS, and Android.

If Red's development was to keep on pace, which is important for multi-OS usability, I do think it would be worth knowing. Quite powerful and easy to learn language, for potentially a wide variety of purposes, with a light footprint.


In reality? None. Both give me lots of trouble. Red doesn't offer a good external program launch, which when things fail, I always drop down to sh. Rebol interestingly enough offers a wee bit more stability. but its age is clearly showing. r3 being open source has a bunch of versions and forks, none of them usable. there's also ren/c which is supposed to be usable, however I cannot build it on a pi4, there is also another attempt which is called arturo, written in nim, this one works but development is only done by a single person.


There’s a few more living derivatives of the OG Rebol; the second of these also has a list of other derivatives and relatives:

https://github.com/metaeducation/ren-c

https://github.com/Oldes/Rebol3


I don't see any sentence nor expressiveness in that. It's the same structure as most method calls.

"Deposit 100 dollars in my account." is a sentence, and that's doable in most languages. It just depends on how high you want to go with it. Functions are ubiquitous and powerful:

    deposit($(100), in(my_account))
And if we remove brackets like a lot of languages (I prefer not to)...

    deposit $ 100, in my_account
Functions remove the need to tie actions to objects too. We can rely on types/interfaces.

    deposit($(100), in(the_river))
We could go further, again, depends where you want to stop. Expressiveness isn't really limited by most languages.


Also, reading like a sentence is not expressiveness. Expressiveness in programming languages is about abstractions, like for example macro capabilities. Reading like a sentence is merely about fluent APIs and (sometimes) syntactic sugar.


Best to read the smalltalk as always embedded in an invisible framework that looks like this:

hey OBJECT !, I want you to ACTION with ARGUMENTS

so ... "hey account!, I want you to make a deposit with $100"


...which illustrates one of the oddities of Smalltalk's vision of OOP pretty well. I've made deposits into accounts, or maybe I've asked banks to make a deposit into an account on my behalf, but I've never (intuitively) instructed an account to make a deposit into itself.


level error!

   account deposit: $100
was the message from the bank teller to the account, not from you :)


Do bank tellers, conceptually, think of themselves as telling accounts to add $100 to themselves? Or do they think of themselves as adding $100 to an account?


... when the bank teller's are software-driven entities, they might :)


Yes, I suppose it's the case that if the bank tellers are written in Smalltalk, the Smalltalk way of doing things make sense.


Yeah, you're supposed to say:

    bankTeller deposit: (100 dollars) in: myAccount.


I'm doubtful that 'reads like English' is 'expressiveness' because language is nuanced and imprecise.

That's not what we want in a software language.

In fact, we should not even call them 'languages'.

If by accident of history we called it 'Machine Instructions' - would anyone have ever tried to make it seem like Enligsh?

Clear, concise, unambiguous is I think what we want. Just enough overhead to keep it clear but not so little that it's ambiguous.


This can cut both ways, though—English-likeness can be bad for a language when it comes to the boundaries of what English expresses well (see https://daringfireball.net/2005/09/englishlikeness_monster). There's a reason we don't program in COBOL!


I must be the only person on the planet who likes AppleScript :)


I want so much to like it, but, even in its heyday, the documentation was so poor—everyone seemed so convinced that its English-likeness made it obvious that they seemed to refuse to document the 'obvious' commands. And now it seems that even Apple has decided to let it languish.


> reading like a sentence.

But therein lies the problem. Let's forget about programming for a moment and talk human languages instead.

In english, you say "Cheese omelet". In dutch, you say "Kaas omelet". In french you say "Omelette du fromage".

Neither is better than the other; it's just how it is. A native english speaker who is learning both dutch and french may posit the feeling that dutch feels 'more natural' and has 'more obvious word order'. But I'm sure you'd agree that this is just based on happenstance; simply because english and dutch so happen to match. There's nothing intrinsically better about putting the cheese in front of the omelet instead of after it. Nevertheless, for a native english speaker, dutch will seem simpler... __right up until the moment you turn "native", and you no longer translate each word on its own back to english first__. Once you've hit that level, there's no difference. At all. You hear the words and your brain visualizes a cheese omelet instantaneously.

The same logic applies to programming langauges. "It reads like a sentence"? What are you on about? If I see this code:

    account.deposit(Dollar.of(100));
I know what that means, __instantly__, in the exact same fashion someone who is entirely fluent in both french and english makes absolutely no difference whatsoever between Omelette du Fromage and Cheese Omelet. Simply because I program enough javascript, java, C#, (C-esque syntax) that __THIS__ is natural to me.

Rails in particular is egregiously in violation of this ridiculous aim to make it look like english (but, fortunately, nothing so crazy as AppleScript). Rails prides itself on being able to write `5.minutes` - they monkey patch numbers to add a minutes function.

But in programmese, of any flavour, that makes very little sense. You want to create a value of type Minutes, or in some languages, you want to create a value by using a function from the namespace Minutes, and this operation that requires a parameter (the amount of minutes). Putting the param _before_ the namespace / class / type / function name / whatever your programming language uses here - is _highly exotic_ - something very very very few programming languages do. Except Rails (I'm going by memory here - I believe the minutes function on numeric types is a monkeypatch Rails adds, it's not stock Ruby). They do it, apparently (in that they call it out in their tutorials) because "5 minutes" reads like english and leave it at that - clearly insinuating that 'reads like english' is upside.

No it isn't.

And that's why "account deposit: 100 dollars." is by no means "easier to read" simply because it reads like an english sentence.


One hundred percent agree. Please stop trying to write really verbose code that looks like some weird pseudo english. Mathematicians realized having a grammar specific for mathematics was a GOOD thing NOT a drawback. Even if you have to learn a few symbols at first.

What I want to see: 5 + 3

What I don't want to see: Add the number five to the number three.


The joke when C++ appeared on the scene was that the successor to COBOL would be named ADD 1 TO COBOL GIVING COBOL.


One of Tcl's most popular object systems is called incr Tcl. Tcl allows some Lisp-like metaprogramming (albeit effectively all stringly-typed, and with fexpr crawling horrors -- where it's really easy to confuse metalevels -- and weird scoping rules), so incr Tcl can be, and is, implemented in Tcl.


The logical conclusion of that reasoning is APL. Everything else looks like some weird pseudo english in comparison.


> Rails prides itself on being able to write `5.minutes` - they monkey patch numbers to add a minutes function.

That can be done in strongly, statically typed languages with either extension functions (Kotlin, Dart) or type classes (Rust, Haskell).

People do it because there are advantages beyond the subjective reason that it reads better (I can speak several human languages and in all of them you would say number-timeUnit - so it's not just English even if it's not completely universal). It's also easier to "look up" functions based on the type of the value, for example.


Don't forget F#'s units of measure! Which by the way are pretty cool, as the compiler automatically infers new units of measure for you:

    > [<Measure>] type km;
    > [<Measure>] type hour;
    > let distance = 60.0<km>;
    > let time = 0.5<hour>;
    > let avgSpeed = distance / time ;;
    val avgSpeed : float<km/hour> = 100.0
(And of course forbids physically illegal stuff such as adding values with different dimensions)


> In french you say "Omelette du fromage".

No you don't, that's literally "Omelet of the cheese". You say "Omelette au fromage", which is "Omelet with cheese".

I do agree with your broader point, though.


>Rails prides itself on being able to write `5.minutes` - they monkey patch numbers to add a minutes function.

In languages like Nim with Uniform Function Call Syntax this is actually completely natural and universal: f(a, b) and a.f(b) are completely equivalent in all cases. So if you have an ordinary `minutes` function that takes a number and returns a time/duration, you can write either 5.minutes or minutes(5) as the fancy takes you. No special monkeypatching required, it just works everywhere for every function and every type.


>But therein lies the problem.

Exactly. This is why I dislike SQL. The relational model is great, but it was hamstrung at birth by the foolish insistence that it "read like English" so that non-programmers could write queries. Now we're stuck with a deranged syntactic mishmash.


Interestingly, a large number of the people actively developing Pharo seem to be native speakers of French and Spanish. People from Inria are the lead devs, and it’s got a lot of momentum with South American universities too. I guess they see value in it as a pedagogical tool, at least.


I definitely understand the argument that different human languages have different semantic patterns. The only non-English language I know (reading, not speaking) is classical Latin, which likes to have nouns and verbs at the opposite ends of phrases; after reading a lot, it just starts to "feel" right.

    account.deposit(Dollar.of(100))
I also know what this means, but somehow it just doesn't "feel" right. Maybe it's because all the other words are in English, so I want 100.dollars to follow English word order? But account.deposit(...) feels much better to me than deposit(into: account, ...), which is the "wrong" word order. I'm perfectly willing to accept that I just have a sense of what "feels" good to me and it's not necessarily logical or reasoned, just a general aesthetic of nouns playing in a world of data.

As an aside, I always find it funny when people use "monkey patching" in an attempt to decry giving language users expressive power. I love monkeys! I love monkey patching!


I'm still not clear on whether or not you are a native English speaker, but the point being made is that the expressiveness of a programming language shouldn't be tied to the semantics of a spoken language irrespective of whether the majority of the keywords are expressed in some given language (in this case English using Latin alphabet).


The derogatory and inaccurate use of “monkey patch” to describe adding methods to an open class identifies you as a Python advocate, so grains of salt applied, but:

I can’t speak for this particular Rails usage, but one of the most powerful things you can do with Ruby is build domain-specific languages without modifying the language itself. *This is a core feature of Ruby.*

The criticism you’re making is one of the Rails DSL — there’s nothing in Ruby preventing you from instead writing account.desposit(Dollar.of(100)).

Put another way: This is like people criticizing RISC-V for not having multiplication in the core ISA — they don’t seem to grasp that RISC-V is an ISA construction set. Ruby is a language construction set.


"monkey patch" is frequently used by Rubyists without anny derogatory meaning.


True, but it was taken on by the ruby community as a badge of pride after being used as a slur by the aforementioned other community, IIRC.


I first heard the term in reference to how mootools messed with prototypes of JavaScript built-ins; at that time, I had no experience with either python or ruby.

Whatever context the term may have originated with, it far outgrew those origins. I definitely don't instinctively think of python programmers snubbing ruby when I hear the term.


really, it should be:

  account acceptDeposit: 100 dollars.
accounts don't deposit money, they accept deposits.

Or, for a more realistic domain model:

  ledger credit: accountNumber debit: cashHoldingsAccount amount: 100 dollars.


Probably part of why Smalltalk died. The C syntax and the BASIC syntax became ubiquitous, and things like Pascal and Smalltalk were just too weird. Luckily we have Ruby, which is almost-Smalltalk with a BASIC-like syntax.


> Pascal and Smalltalk were just too weird

A huge reason why C syntax is "not weird" is because its weirdness has been normalized. I didn't realize how absolutely bizarre some of the things in it were until I was an undergraduate teaching assistant for a C programming class for Math and Engineering majors.

The big problems I remember:

- Why {} braces?

- Why A = B? They're not actually equal. This can be a huge conceptual stumbling block.

- Why is this function returning "void"? This makes no sense, that's not a function.

- Why A.B()? Period gets read as a sentence terminator and that function is being called with no parameters, which makes no sense.

- Why do we use square brackets [] and not parentheses () for arrays?

- Why do we need a ';' at the end?

- Lots of confusion over `&&` and `||`.

- Problems understanding `+=` and similar.

Old Smalltalk editors did some things to make the language more understandable, such as turning `:=` into an leftward pointing arrow and `^` into an upward arrow. Once I saw this in practice, it made a lot more sense to me. Not that Ruby and Rust both have the `|vars|` syntax.

Pascal-family languages like Ada look "too weird" because most people learned a C family language early on. It'd be like saying Russian or Japanese is a weird language because you only know Romance languages.


> - Why is this function returning "void"? This makes no sense, that's not a function.

Personally the distinction between subroutines and functions always struck me as overly math-centric thinking, because it's not an interesting difference as soon as non-local state exists, which is almost always the case.

> - =, +=

I don't quite get why this remains contentious; even in math these are somewhat overloaded ("=" in equations vs. "<=>"/"=" for equality of equations, for example); code simply is not math. Why would the symbols mean exactly the same thing in a different context?

> - Why {} braces?

Big braces have always been used to group stuff together (e.g. case distinctions, summaries etc.), so it kinda makes sense to use that for groups of lines, i.e. code blocks.

> - Why do we need a ';' at the end?

C/UNIX was originally written using actual teletypes, so not only does ";" make it easier to parse, but it also gives you a very explicit marker that you definitely reached the end of the statement. That matters when every line you're looking at when interactively editing a file uses up some paper.


> - =, +=

It's related to the same problem with = as assignment, note GP's context: Math and engineering majors. They have been taught, assuming they paid attention, that = is not an assignment but a relational statement. If they've never programmed before, having = as a thing that changes the system state is still new to them. This is a common issue I've seen in tutoring over the years, where students' mental model is closer to Excel than to <standard programming languages>. That is, if you do this:

  a = 10; b = 20;
  c = 3*a+c;
  printf("%d\n", c); // prints 50
They aren't surprised, but then they do this:

  a = 20; // this demonstrates part of their confusion, they half-get that it is an assignment
  printf("%d\n", c); // prints 50 ?!?!?
They expected 80. So they haven't fully internalized that `=` means assignment and is not establishing a relationship between the thing on the left and the formula on the right. One of the key things that helps is teaching them to "read" a program, and to read `a = 10` as "a gets 10" or "10 is assigned to a".

> Why would the symbols mean exactly the same thing in a different context?

When you have one mental model that you've been taught for 12+ years and are 18-20 years old and don't have a ton of experience, this is confusing. That it is not or was not confusing to you is either because you had a learning experience that specifically targeted this confusion, you made the connection more readily (maybe closer to the top of your class than average), or are looking back on your past and neglecting how far you've come since you were that age and had that level of understanding.


A good example, but unfortunately harder to follow than it should be because you accidentally wrote "3 * a + c" when you meant "3 * a + b". Unless you are making some very subtle point about uninitialized values?

To make this a slightly more useful comment, I'll mention that I confirmed that even with -Wall neither clang-6.0 nor gcc-9 gives a warning about the second assignment to "a" being unused. This would often be a nice thing.


That was indeed a typo on my part.


I understand the confusion with = for assignment, but isn't the solution usually to use symbols like := or <-? So shouldn't += and friends be on the easy side of things to teach?


It's hard to use := or <- as notational conventions when teaching C-syntax languages to novices. If you do, you're teaching them two things: The logical representation and the actual representation. They already have a lot in their heads so this only creates more confusion, "Why do I get a syntax error when I write 'a := 10'?" "Because that's just for the notes, not the code...".

The problem with += (IME) is with the incomplete and incorrect model that students have, += is one of the situations that can force a realization that = in C-syntax languages is assignment and is not a relational expression. But if they haven't grokked that yet, it's jarring.


> Personally the distinction between subroutines and functions always struck me as overly math-centric thinking

Not really, many programming languages generally considered math-centric are perfectly fine with functions returning (or taking) a unit type of some sort, category theory (and even its predecessor abstract algebra) has a lot of use for initial and terminal objects, etc.

It’s more like mathematicians used to be vaguely uncomfortable with non-referentially transparent things when computation as a mathematical object was new. They realized the error of their ways pretty quickly, all in all, but a realization such as this can take decades to make its way through layers of educational materials.

> I don't quite get why [ = for equality] remains contentious

Because it’s a huge problem when teaching, even if it isn’t for competent practitioners. Maybe it wouldn’t be if we put CS (and graphs, and games, and lots of other things utterly lacking in prerequisites) in elementary-school mathematics where it belongs, but if wishes were horses I’d have a racing franchise by now.


Yes, "math-centric" in the sense of high-school math (=> "functions are R->R").

I mentioned the = thing because I only ever see this brought up by what seems like a very particular developer tribe. I used to tutor 1st semester CS students in programming C and Java - for many this was the first time they were programming - and I don't think I've ever seen someone confused about it. Lots of other things though; programming is hard.


> Personally the distinction between subroutines and functions always struck me as overly math-centric thinking, because it's not an interesting difference as soon as non-local state exists, which is almost always the case.

It's about command/query separation which is still a best practive to this day.


Re: the distinction between subroutines and functions, I found (the first section of) this chapter to be interesting.

https://letoverlambda.com/index.cl/guest/chap5.html


>Personally the distinction between subroutines and functions always struck me as overly math-centric thinking

Well, the word is taken from math, it seems pretty rude to take a word while preserving nothing of its original meaning. A function is a mapping between sets, it has nothing to do with abstraction or reusability or any of the dozen other keywords said when introducing the concept in programming courses, it's just an association between sets satisfying certain (relaxable) constraints.

From this perspective, a function that returns nothing is a hilarity, it collapses all elements of its domain to a single point. A function that takes nothing and returns nothing is a deviancy, where is the mapping then if nothing is taken and nothing is returned?

Keep in mind that the usage of 'functions' to denote callables* is a new thing that happened probably around the mid to late 1980s. Computer Science always called self-contained pieces of code '(sub) procedures' or '(sub)routines' or '(sub)programs'. Fortran, the oldest programming language, honors the difference until now. Pick any conference paper or book written before 1980 and I guarantee you that 'function' will denote a literal mathematical function used to describe some property of an algorithm or declare a certain constraint on a computational object, and that callable code blocks are always called one of the terms above or their variations.

>because it's not an interesting difference as soon as non-local state exists, which is almost always the case.

The thing is, there is no such thing as 'state' with functions in the first place. The word denotes something in a world that knows nothing about change or time, taking the word and redefining it to include those concepts is meaningless. Imagine if I took numbers, added physical units to them, then insisted that this is the mathematical definition of numbers all along. That's what happened with functions.

Also how exactly is the difference between pure subroutines and mutating subroutines irrelevant when non-local state is involved? it's the exact opposite, the difference is an irrelevant and opaque implementation detail if the mutated state is callee-local and never leaks to the caller, otherwise it's an outsized obsession of life that can mean the difference between a good weekend and a sleepless 24 hour and all things in between. It's exactly when it's non-local that mutable state is revealed as the horsemen of death it is.

* : see? even the verbs don't make sense: how exactly do you 'call' an association? it's a mapping, you either 'apply' it or 'refer' to it or 'look up' an element in a table listing (a sample of) its input-output pairings. Similarly, you don't 'return' from a function, you never 'went' anywhere to return, you had an element and used it to get another element with the help of a mapping between the 2 sets containing the 2 elements, this 'happened' instantaneously, timelessly, there is no instruction pointer in math breathing down your neck and telling you to return here and go there.


> A huge reason why C syntax is "not weird" is because its weirdness has been normalized. I didn't realize how absolutely bizarre some of the things in it were until I was an undergraduate teaching assistant for a C programming class for Math and Engineering majors.

To give another PoV: I've taught javascript to absolute beginners (graphics design students coming from humanities studies with pretty-much zero programming or general "scientific" ability) and the syntax, fairly close from C, was very much not an issue for them, unlike the maths required ; I had to spend much more time explaining how transformations in a 2D plane, vectors, etc... do work, than correcting syntax mistakes.

In ~20 hours of class they were pretty much all able to write small programs with for-loops, conditions, etc. which did nice visual effects in p5.js so I'd say that teaching the basics of programming is an entirely solved problem in 2021 ; whatever the topic, you cannot expect to teach stuff faster to a whole classroom.


> - Why A.B()? Period gets read as a sentence terminator and that function is being called with no parameters, which makes no sense.

What C syntax is this referring to?


You can do that, with a structure and a function pointer.

  struct a {
    void (*B)();
  }

  struct a A = { .B = ... };
  A.B();


Great example, especially considering op found that he added that example as a mistake :D


I severely overloaded a reference to C-family syntax and should have provided multiple examples instead. I erred, by trying to avoid C, C++, Java etc. specific comparisons.

What I should have written:

- Why is "Foo()" a function is being called with no parameters, which makes no sense.

- What is "A.B" Period gets read as a sentence terminator. I learned C++ and Java very early on in life and had never considered A.B to be an issue.


I think the only "hard" part about the syntax of C are pointers. Reading e.g. i++ *a->b[0]


I think Smalltalk's demise was really from the fact that it was a entire environment that had to live in a virtual machine.

Especially in the 70s and 80s, that was a huge performance barrier.

Contrast this with C, which probably won because of its largest benefactor, Bell Labs and UNIX. Smalltalk in some sense was a competitor with UNIX itself.

Smalltalk's influence is everywhere, but the sad thing about it is that it's dev tools were so much ahead of time of anything else.


There are Smalltalks that don't live in a VM. I still contend that the Smalltalk vendors overpriced their wares in the era of Turbo Pascal and they all went a bit Java crazy which amounted to nothing.

It is a shame that Self and F-Script didn't gain a bit of attention.


Self was quite influential in the language development world however, perhaps most so in JavaScript itself.

StrongTalk was also very influential, because many of its developers also ended up working on core parts of the JVM and V8 JITs both at Sun and Google.


QKS was a prime offender complete with asking a completely sincere “wait what happened?” afterwards.


A pity about F-Script for sure, if only it had targeted app builders. Smalltalk history seems to be littered with abandoned projects. Amber ST in the browser and F-Script on OSX come foremost to mind.


Don't forget Ambrai Smalltalk which had a really cool beta version but then disappeared.

F-Script was really awesome, even more with F-Script Anywhere


I think none of the reason applies but it's tongue in cheek.. I think it all points at cultural maturity. Same smalltalk today might be well received because machines are wide and fast and people have seen more languages. It's surely easier to show ST to py or js coder today now they've seen large syntax changes and paradigms (FP, async etc)


Pharo is a Smalltalk, but they're ok with moving in new directions.

As a Python coder, I played with Pharo and tried several tutorials and read a book on Smalltalk-80. I get the gist of things, but have trouble actually writing the code as things aren't obvious and there is no StackOverflow or cookbook for common tasks. It took me forever to figure out how to do file IO and that sort of thing. The other problem is that deployment isn't just running a script, but deploying the image and runtime of some obscure language nobody has ever heard of in enterprise software and no IT department is going to be cool with it.



I think most users of Cincom Smalltalk (and other esoteric language users such as Volvo using Dyalog APL) occurs most often due to historical reasons. Please note that I don't think poorly of these languages and would use them over something like Java in my own pet projects any day.


> historical reasons

Of course, mission critical business software still needs to be deployed long after fashions change.


enterprise is rarely a good for esoteric stuff anyway

i actually meant pharo above, i never used genuine smalltalk, just what the pharo mooc gave us


Pascal is actually one of the few languages that is quite readable, even for novices to programming. That's no coincidence, it was designed that way.


Agree 100%, and in fact I'm happy to see that someone shares my opinion on this. It's so clear. To me, it's the best beginner language out there, and I'm kind of sad that it learned programming with other tools, and only a few years later I discovered Pascal.


Yes the only "weird" thing in pascal was pointers and pointer dereferencing with the caret ^

I loved pascal syntax.


The caret is because ↑ (arrow up, in case HN drops it) wasn't really "typeable" (or even available) in most computers. I'm not sure if Wirth's Pascal even had the caret - i do have an old book about Pascal which uses the arrow for pointers, but i remember seeing the caret in various dialects.

IMO Pascal actually has much better pointer syntax than C, even with the caret (which is basically a pointer/arrow up without the tail):

1. Pointer de-referencing is done via something that looks like a pointer and doesn't reuse some math operator (despite writing C for more than two decades i still pause for a bit whenever i want to multiply a pointer to a number)

2. Getting the address of something is via the "at" character @ (which kinda makes sense as a pointer to something is a way to refer "at" it), no way to mix the two

3. No special syntax for referencing a member of a record (struct) through a pointer, all record members are referenced using a dot ".", all pointers are de-referenced through the caret "^" so of course all members to a record pointer is done through using both of them: "^."

Also i think that the reason C has -> is because in C pointer de-reference is a prefix whereas in Pascal is a suffix so without it you'd either have to write (*ptr).foo. Pascal avoids that by having both be suffix operators.


> Also i think that the reason C has -> is because in C pointer de-reference is a prefix whereas in Pascal is a suffix so without it you'd either have to write (*ptr).foo. Pascal avoids that by having both be suffix operators.

That distinction comes from early C (pre-ANSI / K & R C), where structures were really definitions of offsets (and said offsets were global, you couldn't have different 'offsets' for a member with the same name in different structs).

Say you had a struct 'struct mystruct {int a;int b;int c};':

You could do '200.b' to access the value at the 'b' offset of the memory location '200' ( '*(int*)( 200 + offsetof(struct mystruct,b) )' or '((struct mystruct*)200)->b' )

And '200->b' would access offset 'b' of the memory pointed to by memory location '200' ( '*(int*)( *(intptr_t*)200 + offsetof(struct mystruct,b) )' or '(*(struct mystruct**)200)->b' )


ASCII actually had up-arrow instead of caret before 1967/1968, although that was slightly before the birth of Pascal (published in 1970).


Yes, the preliminary (1963) ASCII had an up arrow instead of the caret and a left arrow instead of the underline. DEC, Xerox and others built equipment around the 1963 draft and failed to change when the final version of ASCII came out. That is why when Pascal and Smalltalk came along later they used the "wrong" characters.

In the case of Smalltalk, it was Digitalk's "Methods" (the precursor of Smalltalk/V) that adopted := for assignment in place of the left arrow (though the IBM PC character set actually had one, just not with the same code as ASCII 1963) since all of its tutorials were aimed at Pascal programmers.


Hey there Jecel, how are you doing? Any progress on your super interesting projects?


Yes, C got that bit right. -> made a lot more sense.


In Ada (Pascal derivative), there's implicit dereference so we just use it like normal, `A.B`.


Which has pros and cons: a pointer indirection can be expensive so the potential additional cost is hidden and pointers semantic is so different than hiding their usage is a bit risky.. That said this simplify refactoring and is much less 'noisy' to read. My preference is Pascal style but with an @ instead of a ^ which feels a bit weird.


> Yes the only "weird" thing in pascal

I guess you forgot about the semicolons which must or must not be there depending on location. And the final dot.

And, if we move a bit away from pure syntax, strings, even modern ones, which start at 1 for backward compatibility reasons with the original very limited Pascal strings, while dynamic array start at 0 (and original limited pascal arrays start wherever you like).


Semicolons are separators in Pascal, not terminators like in C/C++. The context of usage is different.

The final dot is clarifying the end of the program or unit. It also makes a more clear distinction between the main body or subroutine of the program versus other functions and procedures that are only component parts.

I don't think people are saying that Pascal is a perfect language, as none are, but rather it's an easier to understand and read language. Many teachers would agree with that assessment.


procedure vs function is weird too. And the period required at the end of the program.

I remember learning Pascal and C around the same time coming from BASIC and assembly and Pascal didn't seem particularly easier only more verbose. New concepts like types and pointers were much more of a hurdle than syntax.


Procedure: something that has only side effects.

Function: something that may have side effects but that also returns a value.

Pure Function: something that only returns a value, and has no side effects.

That's how I always understood the terms.


I believe it was mostly economical circumstances just like the other poster said. People put up with everything as long as there is a market and they are getting paid.

As for Smalltalk I can say that it's the only language that has never clicked with me. I have tried the usual languages including Lisp and some weird ones like Forth, Factor and the APL family and never had an issue with those but with Smalltalk I can't go beyond writing factorial. Actually if you sat me in front of a Smalltalk environment it would take me ages to figure out again where to click in order to even have the chance to create such method. The biggest problem with Smalltalk is that you have to give up your tools in exchange of some alien technology that isn't really that good to begin with.

Disclaimer: I have tried Pharo, Squeak and some commercial offerings such as Cincom.


Compared to C, Pascal has the less weird syntax.


I doubt it. C++ syntax is all of: bizarre, hideous, and ambiguous and yet it never limited C++ because at the end of the day C++ was extremely practical. Smalltalk didn't take off (Im not going to say died because it's not dead) because the development tools were expensive and the runtime was frequently not fast enough and you needed a very powerful for its time computer to use it.

Also I think most super popular languages have a niche. Whether its webapps, text processing, low level, etc. Smalltalk lived in its own world and it was hard to integrate with the OS and other capabilities of the system, (try writing a wrapper for like OpenGL or other libraries for example) and I think that somewhat prevented it from finding a great niche to thrive in.


I also disagree with your assessment. Pascal has greater readability in comparison to C, so it's "weirdness" is in the sense that it's more verbose. Arguably, the inherent problem of C family languages is their terseness tends to make them more cryptic and symbolic. But because of their popularity, many have become used to the eccentricities.

Often those who learned C family languages first (C, C++, C#, Java, JavaScript...), can feel there is "something wrong" when viewing the syntax and structures of other languages. When everybody only wears dark blue or black, somebody wearing purple or beige could be considered "weird".

The creator of Ruby, Matsumoto, was a C++ programmer. It appears his intention was to make the language a bit more verbose, as is Pascal and BASIC, to increase ease of use and readability more than exists in C++. A person who used Ruby, would probably find reading and adjusting to Pascal or Lua much easier to do.

Smalltalk gets a bit "weird", because of how they do OO. The structure and syntax used reflects a different way of thinking. Saying that Smalltalk "died", seems to be part of this odd labeling for any language not in the top 10. Are Rust, Kotlin, or Go dead because they never were nor are in the top 10? Smalltalk was never that tremendously popular to begin with, but it certainly didn't die. Go check out Pharo (https://pharo.org/).


I don't program in Ruby but every time I look at it I see something different depending on who wrote the code and what their personal style is. It seems like it has every syntax in there somewhere.


IMO that's one of the biggest weaknesses of Ruby. The language offers lots of different ways to do the same thing. You can say that makes the language more expressive. Sure, but it also means as a newcomer, there's a lot more language features to learn about. It makes the language less approachable to outsiders.

Python and Ruby occupy similar niches. Python has many more libraries, so people will say, that's why Python has been more successful, but IMO, even if Python and Ruby had as many useful libraries, most people would still choose Python, because it's a simpler and easier to learn language. That may have contributed to Python getting a headstart in the beginning.

I'm sure some people would say that's a case of "worse is better", but I think you also have to have some empathy for other programmers. When collaborating on a programming project, having a project that is easier for others to understand is easier. Having a language with less weirdness, less peculiarities and less complexity is a plus.


I think it’s much simpler than that. Ruby didn’t have good documentation in English until the mid-2000’s. Python was in use by the English-speaking world before the turn of the century. Documentation + you can generally understand it at a glance == total Python dominance.

Looking at recent Python code, it also seems like the simplicity is being lost in the rush to add features.


> Looking at recent Python code, it also seems like the simplicity is being lost in the rush to add features.

My inkling is that this is because it is hard to have a general purpose language that lends itself to both novices and experts, and to small scale and large scale. Not impossible, but hard. Those categories desire/need different things, and will use the language in vastly different ways.

BASIC (for all its problems) was a better first language for many people than C or Fortran, but BASIC also didn't scale well to larger systems (structured variants scaling better). Then you start getting BASICs supporting OO and other features which complicate them and lose the appeal to novices, but more effectively meet the needs of intermediate-to-advanced users and maintainers of medium-to-large scale systems.

See also Pascal and its evolution. From a small language to a still small but not as small language in Delphi and others. For the novices, they can still use that small core. But it's now harder for them to onboard with a larger project or a project developed by more advanced users of the language. Especially as the standard library (for the language implementation, if not the language proper) grows.

Scheme, over the various revisions, has seen a similar conflict, culminating in the effective rejection of R6RS and the division into small and large for R7RS.

And those are languages that were largely meant to support novices and learners. Python started off similarly. Now it's older, and its users have aged, and they want to do more powerful things with it and maintain larger and larger systems with it.

On the small vs large side, look at the evolution of JavaScript. It was literally meant for in-page scripting, to do small things and not be the larger system, but a mere component. Like a shell script that copies two files contrasted with the actual OS or shell implementation. But now 25 years or so later it's a vastly different language, and people are building distributed systems on top of it.


You could create nice GUI programs with Delphi with just basic Pascal knowledge, you didn't even have to know about pointers, initializers, virtual functions, templates or any of the crap that comes with C++.


My point with it, though, is that even though you could still use that straight-Pascal core, the language (Delphi) permits more. Which, I presume, many if not most advanced users and large system maintainers took advantage of (my time with it was brief, and I did only use/learn the core Pascal parts).

Python is the same way, there is still (and always has been) a core that is particularly well-suited for novices and a slightly larger core that is sufficient for any small-to-medium system. But as you gain expertise and want to use the language to do other things, or to develop larger systems, you will likely exceed that core. Delphi with Object Pascal was similar. You could still use that core, and accomplish a lot (same with Python), but you cannot guarantee experts or larger systems won't exceed that core.

And that's the language dilemma: How to appeal to both novices and experts, small and large system maintainers? The features that each will want or need are different. Go stayed pretty stable for a decade and kept to its mostly small core, but even it has added generics now because people (maintaining larger libraries, in particular) are chafing under its present constraints. And with these changes, you'll see a (potential, may not happen I suppose but I'd be surprised) major shift in the way the language is used by more expert users that pull it away from its previous model.


> Looking at recent Python code, it also seems like the simplicity is being lost in the rush to add features.

this has been true for a while, the 'zen of python' was lost a long time ago.

i think this is partially because of how much commercial popularity it has, and all the different types of things people need to do with python.


> you can generally understand it at a glance

You're probably right about the availability of documentation, but I also think Python is much easier to generally understand at a glance. Less features, less quirks means the language is easier to learn.


    I don't program in Ruby but every time I look at it I see something different depending on who wrote the code and what their personal style is
I'd say this is a plus, at least in certain dimensions. One of the best descriptions I've heard of Rails' ActiveSupport (a collection of extensions to built-in types included in Rails) is as a dialect of Ruby, one specific for developing web applications. Other domains could and should use different dialects.


The only way I've seen Ruby work professionally is by using tooling that prevents developers from getting too clever with creating write-only code.


That's a problem with LISP-style languages too. Too much flexibility and dynamic syntax leads to write-only languages, or at least languages that are write-only-by-the-original-author.

You can see the opposite end of that spectrum in Go, which can be readily read by anyone since there's generally only one good way to do anything.


If you believe this, it's on you. If anything Smalltalk is easier to read than C++, as it has way less semantics. Probably closer to 1.4-era Java amount of semantics (but with far more power, e.g. closures for one).

You're just knee-jerk reacting to a different syntax.

(You might not like the "image" approach, but that's orthogonal - and not even necessary of all Smalltalks. But you should have absolutely no problem reading and understanding the language's syntax).


The Smalltalk syntax is pretty esoteric, but even if you become used to it, the fact that it requires all parameters to be named makes it an exceptionally verbose language that takes longer to parse in your head than most.

I much prefer more modern languages that allow you to explicitly name the parameters when you need to, but other than that, never requires it (e.g. Kotlin and Swift).


I think you have to separate out verbosity that adds clarity vs verbosity as ceremony.

For instance, seeing "public static void" all over the place in java is irritating.

On the other hand, if I'm doing a code review and I can't do a quick "jump to definition", I'm much happier reading code like:

    t rotateAround: v by: 90 degrees toRadian.
Vs.

    t.rotate(v, 3.14/2)
Sure the former is slightly more verbose (not by much though), but it tells me so much more and I don't need to look anything up. Also even though it's longer, none of it is fluff or ceremonial.


You are trying to excuse Smalltalk's excessive verbosity by pointing out Java's excessive verbosity.

Yes, Java is excessively verbose. No disagreement there. But so is Smalltalk.

Your argument is basically whataboutism.

My point is that Kotlin and Swift both solve Smalltalk's mistakes elegantly by making the parameter name optional. Use it if you have to, but omit it otherwise. And as it turns out, most of the time, you don't need to mention the name at all.


Yes Smalltalk is verbose by design.


Why would anyone think that a verbose language is a good idea?

Explicit? Sure.

But verbose?

There's no good reason for that, except that when Smalltalk was designed, we thought it was a good idea.

We know better today.


> Why would anyone think that a verbose language is a good idea?

What if you are a "sometimes" programmer -- you write some code, then come back to it months later. In many ways this was the intent behind the development of early personal computing. Verbosity is an advantage in these cases because in theory it becomes easier to discern what is going on without having to be immersed in the language, frameworks, and environment all the time.


This is not an argument in favor of verbosity, it's an argument in favor of static types and type inference.

Keep the verbosity to a minimum while making the code easier to read, understand, and maintain.


They said “without having to be immersed in”.


We sometimes think we know better.

There is not an objective universal boundary between explicit and verbose. Some readers will need more, some can guess correctly with less.


It wasn't too long ago, some people were defending Objective C's verbose naming schemes. "We know better today" sounds more like a fashion statement than an objective one. Opinions on coding styles tend to change with the languages that become popular. Granted, I do prefer explicit short over verbose.


I never thouht of Smalltalk as being verbose. It has basically no boilerplate code, almost no syntax and good Smalltalk code is usually well factored. In Pharo, average method has 5 lines (median is 3) of 32 characters (median is 24).

Usual method in Smalltalk, including its definition, is shorther than this sentence.


> In Pharo, average method has…

Do you mean in base Pharo, or do you mean in an enterprisey system built using Pharo?


These are the statistics from base Pharo. Enterprise systems will probably have, in average, longer methods because of longer domain-specific names and tests that are usually more descriptive.


I am not a programmer but can read Ada Language :D


kudos you're an embedded problem solver


When reading code, skimming is more important actually. C-like syntax (symbols instead of prose) makes skimming easy.


> a negative | (b between: c and: d) > ifTrue: [a := c negated]

> As a reader, you should be able to tell that “a” is sent message “negative” (no parameters) which comes back true or false; “b” is sent message “between: c and: d” which also returns true or false. The results are ORed together to become the receiver for the “ifTrue: [a := c negated]” message.

When messages are sent to boolean values, the language is harder to read.

Earlier in that into we were told that the first argument's preposition is always fused with the name of the method/message/operation, while subsequent prepositions aren't thus fused. That also makes the language hard to read.

We are given examples of methods/functions which are adjectives, e.g. "negated", while others are verbs in the imperative voice, e.g. "make", "rotate" etc. That also makes the language (or its idiomatic use) harder to read.


To me its a bit like going on holiday and renting a car with the steering wheel on the other side. Takes a little getting used to, but whole populations can cope with driving on the right, or the left. Smalltalk has a beautiful simplicity, allowing one to express really complex ideas, which to me seems like a super-power. But being image-based can be a pain especially when working in large teams. Merging in everyone's changes could be a PITA.


Unless you were using fine grained version control ENVY/Developer.


Disclaimer first… I was an avid Smalltalk advocate from 1992 until 2012. I worked at Cincom for 6 years.

A few thoughts.

For better or worse (worse in the final analysis I guess), Smalltalk doubled down on an odd proposition. Instead of tools and compilers and language syntax/model being orthogonal/independent things, what could be leveraged if they were highly coupled? If you read the Byte article, and some of the other seminal Smalltalk papers you see this theme.

Smalltalk syntax really struggles outside of a Smalltalk environment. I tried GNU/Smalltalk and a couple of other “IDE-less” Smalltalk in VIM. I’m very comfortable worth VIM. It just didn’t scale well.

But it was a dream in a well done IDE. For the last 10 years, I do C(++), Elixir, Kotlin, Python, Swift/ObjC in a variety of VIM, PyCharm, VSCode, XCode, AndroidStudio, Eclipse, and QT Creator. The IDEs just don’t go as far at all here. The text editors are more modern, but the ability to work with (navigate, refactor) the code at a high level is nothing compared to what it was in some of the better Smalltalk IDEs. To date, no refactoring engine has approached the level that John Brant and Don Roberts did for the original refactoring browser. Unit Test integration at the code browser level existed before the other NUnits were even built. The Smalltalk debuggers were so cool. Interactive process/context inspector/manipulators would have been a better term.

I’ve theorized that the reason Smalltalk the language and Smalltalk the syntax could marry well is that they found a sweet spot in language complexity that made the IDE easy ish to implement and manipulate code, at a syntax level and at a code structs level. Smalltalk syntax existed really only at the method level. Smalltalk code structure was modeled in the “image” as a code database more than as a textual flattening.

It’s interesting how a paper dated 2000 might give the impression that some archeological find reveals while Smalltalk was not a success. I think that would be a misnomer. I was there. This sentiment was pretty common. “It’s too different” is a pretty timeless trope. All this paper shows, is that just like today, there is a small subset of computing enthusiasts that get excited about new/cool/different things, while the populist/conservative types push for things to mostly stay the same.

Smalltalk required a paradigm shift to appreciate. Most of us have limited resources. We don’t have time to explore every revolutionary paradigm shift; the ingress process is just too high.

I’m not trying to pitch Smalltalk paradigm shift as a worthwhile payment for what you got out of it. Those of us that paid the price to achieve the shift, appreciated what the difference was about, even if we’ve mostly moved on since then. Papers like this were a common “I don’t think the shift will be worth it” sentiment.


> To date, no refactoring engine has approached the level that John Brant and Don Roberts did for the original refactoring browser.

Can you give some examples of the refactoring operations that are unique to that browser and not available in other IDEs (for other languages)?


So the common "refactorings" I see in IDEs now days tend to be things like rename, extract/inline, and a limited amount of class hierarchy change.

Some of the other one's I remember involved parameter add/removal (I think PyCharm can do this one?), extract to component, and high end ways to manipulate the class tree like add/remove/pivot class hierarchies.

There were some fun "extras" too like convert to/from ValueHolder (a ValueHolder is a Pointer with Notifications attached to it).

Where the magic began though was in this very simplicity all-in-one thing. To mess with the Refactoring engine in IntelliJs tools or VSCode, I have to learn another language, do another build environment. In Smalltalk, you were there already. It's all in the same code browser. Just scroll down to that part of the system. The AST is so simple, it's expressed in ~15 Node Types (compare to Ruby which has +90 parse node types someone told me?). The matching node type was a single additional node type. So you could see the code that did the refactorings. And you could use the same match trees they did. So you were minutes away from deriving your own refactorings. The first few times, it took longer than just doing them by hand, and then you got good at it and could do some cool things.

The only newer language that I've seen that maybe has this same "because we kept it simple we can do cool things" ethos to date for me is Elixir. My guess is there some others. My guess, is that like Smalltalk, any of these "mind blowing/changing" language/systems have a small but passionate following, but are not enjoying viral adoption.



I see, the simplicity of the AST certainly makes it easier to add one’s own refactorings, and that’s quite compelling. Thanks for the pointers.


> To mess with the Refactoring engine in IntelliJs tools or VSCode…

https://www.jetbrains.com/help/idea/structural-search-and-re...


One more thing, as much as I appreciate the efforts of the Squeak/Pharo crowd… I don’t think they’ve reclaimed the original Smalltalk synthesis experience yet. Like X11 desktops, they’ve not figured out how to apply the Less is More rule effectively.


I would be interested if you could comment on this further, if not here then maybe in a blog post. Do you mean deeper ability to manipulate the whole underlying system, rather than being confined mainly to the VM?

I put that idea forward because I’ve seen people working with the Emacs/Common Lisp combo wishing for something like that… that it was Lisp all the way down like an old Lisp machine. Seems like some are looking towards GNU Guix to approximate that sort of system.

For what it’s worth, I’m prepping myself to spend the next couple years at least exploring interactive programming systems like these, so perspectives like yours are fascinating to me. I’m not looking for a programming job any time soon (or maybe at all), so I’ve got time to study most seem to think is “alien technology.”


No, sorry. I meant in user polish. Squeak/pharo for me are a mess. The code browser has a variety of inconsistent and frankly just too many menu options. So it becomes not just live code experiment, it becomes a live user interface experiment at the same time. This kind of thing leads to “too many experiments/agendas at the same time” effect (for me).


For me, a programmer who grew up with assembly language and Basic around 1980, Smalltalk is an extremely easy to read language. I have struggled with all the other languages (in the order of LISP, Forth, Pascal, Prolog, ADA, C/C++, Java, Perl, Python, Javascript, Scratch, Etoys). I have read the entire code base of Squeak Smalltalk (200.000 lines of code for the programming language, the operating system, GUI and IDE) and its the clearest and easiest to understand writing of a compleet system in history that I know of. I challenge anyone to prove to us any coding thats qualitatively better (than what Dan Ingalls wrote).

If I had more time I would point out the scientific papers and mailing list/forum/blog posts where there has been fact supported arguments why Smalltalk is better readable and writable than almost any other programming language. Arguments like [1] the syntax is really short and simple [2] or it was developed with children in mind [3][12].

But the OP should recognise that there are (many) cognitive biases at play in his affection or aversion to this or that programming languages just so it confirms to his existing beliefs. And his existing beliefs where formed similar to how the concept of 'mother' is formed in ducks, by imprinting at birth [5]. If he had started out with another programming language, than that would be the language he would defend in a blog post. Its like he is defending qwerty keyboards as being the best keyboard layout instead of the historical inertia and cognitive bias it is [11].

Alan Kay and Dan Ingalls who invented Smalltalk and its syntax in research at PARC redesigned Smalltalk several times to improve it, including its readability while testing it out on thousands of users including children. As good science this has been documented very thoroughly but I lack the time right now to point you to these hundreds of references. Maybe HN software allows me to add these later.....

Maybe OP could design us a programming language (with Ometa [7]) that would be better readably and writable, instead of just voicing his tribal preferences and allegiances?

For those who want to play and code with all the versions of the Smalltalk language since 1972 I can recommend [7] or [9] if they don't want to install it first. Better still, download the best app (and original) Smalltalk at squeak.org [10]. Don't forget to look into Self [13][8]. Squeak Smalltalk is also a VM that has been ported to more operating systems and environments than any other language I know of, even Linux. Due to memory size limits, its hard to put it on systems with less than 1 MB memory, but not impossible. I'm hoping to release a version for tiny microcontrollers with less than 100KB memory someday.

[1] https://wiki.c2.com/?SmalltalkSyntax

[2] https://squeak.org/documentation/terse_guide/

[3] https://www.researchgate.net/publication/221501755_The_Early...

[4] https://www.teachthought.com/critical-thinking/cognitive-bia...

[5] https://cerebromente.org.br/n14/experimento/lorenz/index-lor...

[6] https://www.researchgate.net/publication/220828937_OMeta_An_...

[7] https://smalltalkzoo.thechm.org/

[8] https://selflanguage.org/

[9] https://squeak.js.org/

[10] https://squeak.org/

[11] Recent talks on youtube by Alan Kay

[12] https://smalltalkzoo.thechm.org/papers/EvolutionOfSmalltalk....

[13] https://ourself.io


The author of the article teaches and works in Smalltalk. It's about explaining and justifying the differences that confuse programmers coming from Java and C++.


I can read Ruby and Smalltalk but C++ is like ancient hieroglyphics that require a PhD in classical studies or something.




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

Search: