Hacker News new | past | comments | ask | show | jobs | submit login

What is the appeal of small languages?

If it's simplicity, it seems like complex programs would be supported by complex libraries instead of complex language features, leading to the same level of complexity but with less consistency.

"Smallness" seems to be a sought after feature but I'm not sure why.




I must confess I had to suppress my knee jerk urge to downvote. It almost feels like you're asking "what's the appeal of elegance?" "What's the appeal of Chess, if you want complex gameplay just have complex rules." It almost feels alien that someone couldn't get it.

Here's a simple but perhaps disappointing theory. Painting with a broad brush for a moment, there are primarily two sorts of thinkers: memorizers and logicians. The former have astounding recall, and consequently have no qualms about learning loads of vocabulary. They, for some reason I will never understand, actually delight in learning a foreign language. When they end up in the sciences, it is more often than not some form of biology where knowing all the assorted physiological systems and every cataloged failure mode and the symptoms thereof is of great benefit. The latter can't do any of that, but if you pause for half a second in the middle of a thought they will start trying to complete your sentence by suggesting words. When they find themselves in a foreign country, they figure out how to use the washing machine and vending machines and generally fend for themselves without any help despite not being able to read any of the labels. They might never learn the language, but they quickly figure out which characters mean "road", "park", "river" etc based on nothing more than the subway station names. When they go into the sciences, they tend to end up in math or physics. Newton only makes you memorize 3 things, and from there literally everything else follows if you think hard enough.

So, for the logician type thinker, small languages are just deeply pleasing for the same reason Newtons laws and Chess are deeply pleasing. Those are the antithesis of learning a foreign language. Small coding languages let you know everything while learning as little as possible. The memorizer types must see the appeal of small language the same way I see the appeal of memorizing all the characters in the Chinese writing system. I see no appeal in learning all the characters in written Chinese. Why would anyone ever consider all those characters a sought after feature?


What a lame Mars/Venus theory. Language designers never make complex features in order to have more to learn and catalogue. They are nakedly compromises which are supposed to make certain things easier, maybe even simpler in certain senses (for example simpler library code: more complex features like pattern matching can make for less spaghetti control flow).

Then the retort might be “but they wittingly or unwittingly pursue the goal of complexity for its own sake!”, in which case that would just prove that you have stacked the deck in favor of the “logician” (who makes simple languages for simplicity’s sake—simple).

Another problem is that some language designers are logicians by trade already.

> So, for the logician type thinker, small languages are just deeply pleasing for the same reason Newtons laws and Chess are deeply pleasing.

Chess has Opening Theory. I bet the Half-Delayed Swashbuckler Sicilian just comes naturally to the oh-so exalted logician.

(Then the retort might be, oh I’m just talking about the game in the abstract, not the metagame. Well it is very important how a game is actually played and how a language is actually put to use.)


There are plenty of people who love chess but hate opening theory. They look to variants such as chess960 to get their logician fix on. They also tend to love Go (the board game) and perhaps even Stratego (which has such a game tree that dwarfs the rest).


Chess was such a good example to use in this lame dichotomy that we are now pivoting to Bobby Fischer chess and completely different games.


It's not a lame dichotomy. There are loads of people who detest rote memorization and prefer to solve only the problem directly in front of them. Bobby Fischer himself invented his variant because he hated that aspect of the game. I, personally, empathize with this position as a university student who gets higher grades in pure math courses than in the "easier" applied versions due to the memorization aspect.


Doesn’t matter because it doesn’t apply to language design.


Completely different in that everything is exactly the same except for minor variation to the starting position...


Fischer Chess is solidly outside the mainstream. Just let it go.


I feel like your take is simply too strictly bound to your personal preferences. Small is not the same as elegant. If it sad "Zig, the Elegant Language" that would be something else. Lace and watches are elegant but complex and intricate.

A large language might be more consistent and well thought out than a smaller one. That, again, is a separate detail.

And we're talking about the main selling point of the language. Not just 'oh and its pretty small too.' Of all the things to focus on, it would not be my priority for sure.


> memorizing all the characters in the Chinese writing system

Actually, there's a logic (a stroke order logic and also some common building blocks) to how to build the characters in Chinese (and other similar languages). So I would imagine the "logicians" might be OK with it :)


> Small coding languages let you know everything while learning as little as possible.

Very well put


But its just more library code to learn instead, isn't it?


To me being able to keep the entire language in my head is invaluable. When working with Go for example I know that I can dive into the bowels of some library dependency and I will be able to read it and figure out how it works. This is because the language encourages straightforward code and has very little magic. The code does what it says.

We have to deal with complex libraries no matter of how big or small the language is. A small language that you can keep in your head makes dealing with them easier.

I would also argue that smaller languages lead to more consistency not less simply because there are fewer ways to do things. Look at early Python vs modern Python for example. In very early Python (pre-2000 or so) there was actually "one and preferably only one obvious way to do it". Modern Python with all the features it has grown over the decades is the exact opposite of that. C++ is another obvious example.


But it seems to me language features help the understanding. You'll need to learn whatever library or custom code was used instead of a language feature with the added headache that you need to learn it every time and you'll see many implementations.

That said, I'm used to Java or C# as far as language size goes and I don't feel suffocated by it. I'm not sure if its a natural inclination or a learned skill.


Not every language that is small (in the sense of having few rules and few primitive constructs) is necessarily simple (in the sense of easy to understand). Scheme (or its basic core) is quite small, but it's not easy to understand other people's code due to macros; RISC Assembly is also small but can be hard to understand because its abstractions are so limited. But a language that is very explicit, has reasonable abstraction, and is also small -- like Zig -- makes following the control flow quite easy, and so makes programs easier to comprehend: you mostly need to apply only local reasoning.


Go look at herb sutter's guru of the week articles, and consider how many C++ programmers can actually solve them. Then consider c++ has gotten even more complex in the past 9 years since he last published a gotw.

The main problem is that every c++ programmer has their favorite little bit of complexity in the language, and that favorite bit is different for everyone. So you end up with a codebase sprinkled with the full spectrum of language complexity if you're working with a large team, meaning you need to understand all of it if you want to understand the codebase generally.

At least with complex libraries, the complexity can be safely hidden behind the API. Not so with complex languages, at least in my experience.


Since it is considered a begginers language, how complex do you imagine Python actually is, given that the language reference is 186 pages and the standard library 2159 pages, plus whatever has changed between versions?


I think it is actually fairly complex as you point out. I certainly wouldn't hold Python up as a paragon of real simplicity or consistency. But, it is far, far less complex than any modern C++ version.


Going from N features to N+1 features creates N! new interactions to consider.

For example, if we have a bunch of language features, and we decide to add a new one, e.g. exceptions, we now have to consider:

- How exceptions work

- How exceptions interact with threads; how exceptions interact with dynamic binding; how exceptions interact with dynamic binding in threads; how exceptions interact with mutable variables; how exceptions interact with mutable variables in threads; how exceptions interact with dynamically-bound mutable variables in threads; and so on.

Also, all of the language's tooling needs updating: compilers, linters, documentation generators, static analysers, formatters, syntax highlighters, auto-completers, etc.


That's why algebraic effects are cool, right?


I'd say any feature is cool if it:

- Is small/simple/principled (i.e. understandable)

- Enables many desirable programming styles or capabilities

- Complements other features: ideally working even better in combination; or at least, working in an obvious way

Algebraic effects tick all these boxes IMHO. In particular, there are many languages which feature try/catch AND for/yield AND async/await AND call/return; whereas having algebraic effects subsumes all that, turning it into library code.

Note that we can get pretty much the same thing with, say, delimited continuations; so they're also cool. However, having delimited continuations AND algebraic effects would seem redundant/bloated.


> If it's simplicity, it seems like complex programs would be supported by complex libraries instead of complex language features, leading to the same level of complexity but with less consistency.

In my experience, languages with complex features still have complex libraries. Library complexity is a constant. If you simplify the language, at least you free up a little cognitive load there.

In addition, simplifying the language often implies (or is even equivalent to) minimizing footguns.


Like Smalltalk/Pharo, you have 6 keywords in the language and the syntax fits on a postcard. But all the classes/library/environment is huge and complex.


Binary is very simple you need to memorize 0 and 1 and that's it, screw Newton from one of comments above, right?


If you really want to argue about this, binary makes no sense in this scenario. There's assembly which gets assembled into machine code. Machine code for all intents and purposes is the lowest level that you would consider a language, binary by itself accomplishes nothing.

Now you can go see all the arguments about RISC vs CISC, which is the same argument. Should I have a small instruction set that bloats the final program's instruction count? Or a complex set with slower instructions?


Code is read more than it's written, so clarity is important. The fewer ways there are to do things, the closer everyone is to a common understanding of a given block of code, which makes understanding another programmer's intent easier. In turn, this makes onboarding to a project much more effective, and lets devs reach a minimum level of competency more quickly.

Note that small doesn't imply lacking features. For example, something like a std::transform is often "smaller" than iterating through an array with a for-loop, but it's also clearer and less error prone. It's a result of the language itself providing more powerful data structures, and interfaces that make manipulation of those structures easier, which is what I'd argue "small" is actually shorthand for. I don't want to be using a language that only has if-statements and goto, which would be "small" in one sense of the word; I want to use a language that has the minimum necessary number of keywords, decorators, or meta-languages, and instead provides clear, ergonomic ways to express my intent to the machine.


"Wirth’s philosophy of programming languages is that a complex language is not required to solve a complex problem. On the contrary, he believes that languages containing complex features whose purposes are to solve complex problems actually hinder the problem solving effort. The idea is that it is difficult enough for a programmer to solve a complex problem without having to also cope with the complexity of the language. Having a simple programming language as a tool reduces the total complexity of the problem to be solved."

    -- Warford J.S. (2002) The BlackBox Framework


> What is the appeal of small languages?

For me, it isn't just the 'smallness' of the language that matters, it is the understandability of code bases written in the language that matters.

Having fewer language constructs (especially ones that offer overlapping alternatives) means that programs that solve the same problem will tend to look the same. This makes reading a new code base easier, which makes on-boarding engineers faster. This is the main reason I like smaller languages.

Languages like C++ (that seem to adopt every language feature that can be implemented) enable developers to solve similar problems in vastly different ways. In small programs that isn't an issue, but in large, old code bases it can become a very costly mistake. It can be hard to understand a large code base as it is, but when 100 different developers have touched the system and each has a pet style, you are in for it.


The most perfect code is no code at all. A language being small means it unlocks power without complexity. Smalltalk is a great example of this as it was rewritten over and over until it was tiny.

Of course, "no code at all" isn't useful, so there's a medium to be found.


I consider my most productive days as a programmer ones that I was net negative lines of code. Often those are the days when I implemented the most customer features. There is a lot of needlessly complex code out there.


Unlocking power without complexity is not implied by being small. Logo doesn't unlock power by allowing you to move turtle and binary encoding doesn't make things easier by allowing you to write 0 or 1 only.


Right, and I didn’t mean to imply that it did. But languages like Smalltalk do unlock power.


As the total number of ways to accomplish a task increases it puts more burden on a programmer to recognize the usage and understand the semantic differences between the options. How many ways are there to iterate over a collection in say C++?

Libraries _can_ hide some of this, but then that might also be yet another function or operator that does the same thing. Internalizing when to use one method vs. another adds to the total cognitive load of using the language, and it takes away from the mental capacity available for the problem you are actually trying to solve.

Sometimes these differences are necessary and important, other times they are less so.


The number of ways to do something isn't the problem with C++, it is the number of inconsistent ways, some of which have big footguns. If the different ways were all consistent it would make it a lot easier to remember which was the right one to use in any particular context.


simpler languages are easier to learn and to remember. small languages make software easier to write and to read.

complex features (in a language that does the simple things correctly) are always easily composed from the simple features available.

the antithesis of small languages is C++, which is probably the most popular language on the planet in which 0% of its users know 100% of.

with a small language, i can’t use language features which you do not understand when it comes to read my code or take over maintenance, or even understand it.


Do you include size of the library with the size of the language? If you don't, then the difference in size between C++ (considered very large) and any other language isn't very much. If you do, then C++ is much smaller than languages like Java or Python.

The problem with C++ is not the size of the language, it is how inconsistent it is.


Same applies to Java 19, C# 11, Python 3.10,...

I can do puzzles in any of them, which many will fail to guess, specially if runtimes and standard libraries are part of the question pool.


A lot of complexity is unnecessary, that is what zig tries to avoid

Zig is still pretty feature rich (for instance, full generics support) but remains small and simple


For many situations, a language will add a lot of complexity that doesn't bring much benefit. In the end, a language's complexity can sometimes be a net detriment to its user.

For example, one might be making an embedded program where all memory is pre-allocated up-front and there's no heap usage. There's not as many opportunities to mess that up than your average program. This is where Zig would shine compared to e.g. Rust whose borrow checker would be helping with less, yet is imposing its usual complexity burden on the programmer.


Language is the first layer; it should be as simple as possible.

Libraries then framework are the other layers, built on top of the language.

A language designer is unlikely to understand all the needs of the language users, trying to solve complex problems at the language level can seem neat and powerful for the exact use case it was intended, and also unnecessary/cumbersome/too general or not general enough for many more use cases.


Small means not bloaty (yet).


Knee-jerk reaction to the internal Java that everyone has in their brain.




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: