521 comments

[ 4.3 ms ] story [ 339 ms ] thread
“Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.”

Any suggestions on which languages could fit this criteria?

Zig is one that’s been on my list for Paul's stated reason.
(comment deleted)
Is Zig weird though? I find it eminently pragmatic and a lot of the interest in it comes from people migrating from popular languages like C and C++ (not that C++ isn't itself pretty weird).
From what I’ve seen, Zig has no built-in polymorphism features (no vtables/interfaces/traits), which is _pretty_ weird for a modern language in a good way.
That is just because it is new. If it survives it will end up with everything.
Isn't that forecasting a trend with too few data points? The field is still young and changing.
Oh, I don’t think it is a trend. I rather see it as a curious phenomenon that makes one reflect on the trade offs we usually make when using polymorphism, and whether it’s worth all the time, not only in terms of performance, but also in terms of program architecture.
Interesting. What are the program architecture tradeoffs you are suggesting?
To be honest, I have zero experience programming with Zig. But I imagine programming with Zig would lead to more literal style and fewer, simpler abstractions (no IoC, no frameworks). That might be beneficial for certain kinds of focused-scope projects.
I see. They say you can solve every problem with an other indirection, and ad hoc polymorphism is an instance of that. But there are other ways to enable composition that are seldom reached for when your language makes that easy
Every problem, except those caused by too many indirections.

Each solution uses only a few language features. Different problems call for different subsets. Not using a feature on your favorite sort of problem says nothing about its value. "Ways to enable composition" poorly supported are reached for less. Poorly supporting one of them that has proven frequently useful does not improve a language.

> too few data points?

There have been rather a lot of languages. The field is approaching 70 years old, and still changing, but clear evolutionary processes are seen repeated in hundreds of languages living and dead. The ones that don't grow are the most reliably dead.

It has compile time programming designed to subsume those features. So eg a generic struct becomes instead a compile time function that takes a type and returns a struct
That is a wholly other set of language features, for a different purpose, and is thus no substitute.

Practical languages accumulate features to better address a multitude of common real-world problems. Toy languages don't. Sometimes a toy language is adopted and grown to practicality. People always complain about that.

Zig uses explicit allocations everywhere (if you want to allocate something you need a reference to an allocator) which is pretty unique even for low-level languages (e.g. C, Rust)
Zig is certainly not weird in the way that something like prolog or scheme are.
Besides Lisp, languages like Haskell and F# would probably fit. As would Forth and modern stack languages like Factor.
The APL/J/BQN family of array languages, or Prolog & other Horn clause languages. Both will change your idea of what’s expressible in a programming language.
I'm not a programmer/developer by trade but I do like writing scripts to make my job easier.

I'm looking into APL and Lisp type languages basically to expand my mind as up to now I've really only being using "traditional" type languages.

It's like starting from scratch again.

That's true for everybody, I think.

I find "thinking in lisp, then writing the program out in X" where X is whatever 'mundane' language seems most suitable to the task is often a very effective technique.

Array languages I've tried to learn repeatedly over the years and always ended up bouncing off, so have no opinion there except "personal aha moment not yet reached".

Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell which are covered in "Seven Languages in Seven Weeks" are quite nice for start.
> "Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell"

Do they offer any meaningful differences to an otherwise "mainstream" language - anything beyond syntax, tooling ecosystem and the usual functional vs. procedural vs. OOP paradigms?

Anything I can't just whip up in modern C#, C++, Java or Python if I wanted to constrain myself to a specific subset of features or a specific paradigm?

I get the "it's fun to try something new every once in a while" part but people tend to forget that the distinctions between programming languages have blurred significantly over the last 10+ years.

Haskell's laziness gets you all sorts of control flow that is awkward in or missing from most languages. So I think it's worth checking out.
Well, Prolog for one seems very different. In functional/procedural/OOP you have to write a program describing every step of the way. In Prolog you just have to describe the destination.
Yes, there are plenty of meaningful differences. It's true most mainstream languages in industry are essentially syntax swaps of each other, but Prolog and Haskell are not that at all.
In the case of Erlang the answer to your question about meaningful differences is: oh yes! I could list more, but there are two:

- support for concurrency. After tasting it you never will want to go back to techniques normally used in the languages you listed

- data immutability, which makes reading code so much easier.

Imagine if you could run a Python function backwards and feed something into the return value and have Python tell you the parameters to match. That's the uncomon, twisty difference of Prolog relations. In Python a test whether this combination of length and area makes a valid square:

    def test_square(side_length, area):
        return (side_length ** 2) == area
which says imperatively "square the side length and compare it to the area, return the result" becomes a Prolog relation:

    :-use_module(library(clpfd)).

    square_side_area(X, A) :-
        X #> 0,
        X*X #= A.
which says declaratively "square_side_area holds for X and A if X is positive and X squared equals A". This can be used in the same way as the Python code to ask "does length 5 and area 25 make a valid square, yes/no?" but it can also be queried to find: "given length X 5, can this relation hold?" and it answers yes, if A=25. Or "given area 25, can this hold?" and it answers "yes, when X is 5". Or "are there any solutions?":

    ?- square_side_area(5,25).
    true.

    ?- square_side_area(5,AREA).
    AREA = 25.

    ?- square_side_area(SIDE,25).
    SIDE = 5.

    ?- square_side_area(SIDE, AREA).
    SIDE in 1..sup,
    SIDE^2#=AREA,
    AREA in 1..sup.
Then, unlike the Python, you can combine this with extra conditions outside e.g. "(that), and AREA is between 1 and 25" and have it show all the possible answers in that range:

    ?- square_side_area(SIDE, AREA), AREA in 1..25, label([SIDE,AREA]).
    SIDE = AREA, AREA = 1 ;

    SIDE = 2,
    AREA = 4 ;

    SIDE = 3,
    AREA = 9 ;

    SIDE = 4,
    AREA = 16 ;

    SIDE = 5,
    AREA = 25.
If you can spare 30 minutes for a video, this Sudoku Solver in Prolog[1] shows quite well this style of thinking and its consequences. As you watch it, wonder what you might write in C# to solve sudoku (and how much code), and notice here what there is in the way of variables, loops, recursion, indexing, control flow, etc. This kind of thing "I give the constraints to a combinatorial problem, through constraint propagation find some valid solutions" is one of Prolog's strengths.

It isn't /only/ a built in brute-force search, or a "do everything with recursion" computer science lesson timewaster.

[1] https://www.youtube.com/watch?v=5KUdEZTu06o

TLA+, AWK, jq are also interesting choices.
For 'pg it's just an excuse to talk about Lisp.
Any highly experimental language that is used only by a small group of programming language experts would fit the bill!
Sure! Just curious about what specific languages would fit this description.
I'd add Smalltalk to the other odd list suggestions given.
Assembly language for ARM or RISC-V. It will provide a better appreciation for what's going on under the hood.

You'll also see which high level languages fit (or don't fit) this underlying fundamental model which may help cut through the marketing fluff from their various proponents and provide an unpleasant appreciation of the performance costs of popular programming paradigms.

Metamine - it seems to have been pulled from the internet by its creator, after having given some really cool demos.

What's weird: it allows a mix of declarative and imperative syntax in a style that seems like normal procedural programming. You have a "magical equals" that is actually reactive programming... if any of the terms change, ever, the result gets updated.

Here's a previous thread about it

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

> Pick a language that most programmers consider weird but whose median user is smart

This just comes across as arrogant. You can neither know how smart the median user is, nor does it say much about the merits of the tool. It encourages some weird sense of superiority by putting yourself in a group that's exclusive and think they're smarter than everyone else. There are better ways to pick programming languages than trying to maximise your own pretentiousness.

Yeah that sentence felt quite weird. I’m not sure I would say that “smart” is a rigorously defined term.
Agreed, it is self-congratulatory.

Paul Graham essays decline in value exponentially with the number of times he mentions Lisp in them. He had one that went below 2^-20.

Why do you think Paul Graham essays decline in value exponentially with the number of times he mentions Lisp in them?
I think a similar thing can be said about time. There were a lot of novel things to share in the early days, but these days it seems like his essays have taken a turn toward trite elitism. To be clear, I don't think this is specific to PG, but rather the case whenever someone feels the urge to continue producing for the sake of producing, nor am I saying that I'd be able to do any better. PG obviously has orders of magnitude more wisdom to share than me or most other people.
Needs to do a Daniel Day Lewis and go make shoes for a bit instead? (or whatever DDL is doing)
Probably a good idea for anyone that reaches the level of becoming a “public figure”. Log off, go do something with your hands, and come back in 4-6 months. Might reduce the incidence of formerly respected figures going full crank.
Yes !

Doing something outside of your bubble is great for learning some humility and G-d knows PG could do with some of that.

Once your rich and have made it you can’t emulate hustle mode anymore. Sure you can shine shoes but in the back of your mind you know you don’t have to.
It seems like the trend for the past ~10 years has been towards public figures slowly becoming cranks online. I have no idea why, but it sure seems to be happening a lot.
It is true of those with a Facebook or Twitter account, and it is because they need to get increasingly cranky to maintain the level of attention they have got used to. I doubt a change in algorithm could help much, but it seems worth trying more than once.
It’s not been clear to me if having social media turns public figures into cranks, or if some other process is involved and social media merely observe their descent.
Every one of us has the spore of an inner crank, or more than one, only waiting for air and moisture to burst forth.
I _really_ don't know how you got that from this article.
Yeah, this data simply doesn't exist and trying to judge languages by their community will often leave you with variable perceptions, depending on many factors.
I'm not entirely sure about that. Sure, it's probably not in good taste to claim that, however there are plenty of tricky languages out there that have steep learning curves but that are very capable in their own domains.

Even in lieu of that bad taste or elitism, I'd still like to suggest that it takes more patience, self discipline and perhaps a tinge of being clever to pick up something like C, C++, Rust, Haskell, Lisp, APL, Prolog or even regular expressions than it does Java, .NET, Node/JavaScript/TypeScript, Python and others and I say that as a person who relies on the latter for the most part in their daily life.

It's not that you have to be an outright genius to use any of them, but writing code in them well (for example, managing memory and avoiding C++ footguns) takes discipline and definitely could be applauded on some level, as could using APL, Prolog or regular expressions to efficiently solve problems in the few domains that they're actually good at and suited for.

Personally, some of these views of mine formed after listening to a podcast that talked about APL and someone's experience with it: https://corecursive.com/065-competitive-coding-with-conor-ho...

I think that you're moving the goalposts a bit by focusing on difficulty or complexity. Yes, of course some languages are more difficult than others. But the difficulty of a language is separate from the intelligence of the users of that language.
I think it has to do with active choice. The first programming language that people are introduced to are unlikely to be the "best" for them. The first programming languages are disproportionately java, c#, PHP these days. By extension the talented people mostly move on as they learn new and interesting ideas. This leaves the pool of developers poisoned by the mediocre or bad people who spend their entire careers being expert beginners in one domain. People come to the more exotic languages, like Haskell, as their second, third or fourth language. By default the average developer in that pool will just be much much stronger.

Just because the average developer in a language is bad it doesn't mean that the language itself is bad.

(comment deleted)
> The first programming languages are disproportionately java, c#, PHP these days.

I'd say it depends on what we're defining "first programming languages" as - first PL learnt in intro-level university lecture, or first PL learnt individually? But my impression is that the most popular PL for beginners seems to be Python. And while I'm not really a fan of Python, I understand where that's coming from: Python is relatively simple to learn, has a huge library ecosystem and comes with relatively few footguns.

+1 on this, maybe it was C#, PHP and Java ten to fifteen years ago but it's not the case now.
> But the difficulty of a language is separate from the intelligence of the users of that language.

I feel like this is obviously true when taken at face value, however in practice there are probably loose correlations (not causation) between those two, even if not for the reasons that you'd expect.

I'm not sure whether it was mentioned in the same podcast that i linked, or another one, but there was a very interesting example for Haskell that was offered in one discussion. The argument was that the people who utilize Haskell tend to be more likely than the average developer to have ties to academia (which may incidentally also speak of their cognitive abilities):

  - Haskell is popular for numerical processing, moreso than for the somewhat typical CRUD apps
  - because of this, Haskell is more likely to have materials describing it which are aimed towards an academian audience
  - ergo, those materials won't always be simple step by step tutorials on how to do things, but will sometimes assume familiarity with certain maths concepts and will also focus on solving a particular set of (advanced) problems
  - and when these materials attempt to explain these simpler things, invariably you'll still end up with explanations of what monads are somewhere in there, whereas with something like Python you'd have less overhead and a less steep learning curve
  - as a consequence of all of this, Haskell won't be as popular as Python, or similar languages
In the podcast, the person said that these "weird" (or perhaps "niche" is a better word) languages would be far more widespread if they were made more easily approachable, because right now there are no easy and simple to digest books to recommend to people who'd like to get started with them.

Now, the person might be wrong, since their observations are bound to be subjective and i might be wrong to assume that they hold true in many cases because of how believable all of that sounds, but to answer your question, i'd argue that the average user of Haskell is indeed a bit more intelligent than the average user of Java or many other general purpose languages (even though then we step on the mine of having to define what intelligence even is, where opinions can once again differ).

I'd say that simply happens, because some of those languages are far more approachable and therefore more widely used by a large audience of people, not all of which need to concern themselves with solving the issues that people in academia need to deal with. Of course, there could be the counterpoint that not everyone in academia is brilliant, but i remember seeing some pretty admirable professors and researchers back when i was in my university!

What's interesting isn't the difficulty or complexity of the language, but the difficulty of the problems that language is typically used to solve.

Some languages are difficult to learn initially (like Prolog) but that's not because they are intentionally obscure, but because they need to be different.

By "problems to solve" do you mean

- programming language problems like making certain language features, paradigms and kinds of abstractions available (or not available)

or

- solving actual problems when building software - how to build a maintainable and performant server, OS, web UI etc.

For the second you're better off staying away from the 'weird' languages especially if you care about being productive.

Well, lispers claim that lisp is really good for building programs where the specifications are complicated and not already a solved problem. Smalltalkers claim their environment is incredibly good for prototyping a solution. And array programmers would argue numerical computing is much easier in their languages.
I think by "smart" they mean "reasonably smart" or "smart about the programming language they pick". Some people just don't care and work 9-5 programming jobs without caring about what language they use as long as they get a paycheck.
No. He means "clever" or "inquisitive."

The way I think about programming changed a lot from having used different programming paradigms. Many programming paradigms have little real-world value, but they do make you think about computation, abstraction, and lots of other concepts differently.

That grows your brain in ways which are useful when you go back to your 9-5 Python/JavaScript/Java/C#/etc.

I no longer have time to do these sorts of deep dives, but I did this a lot when I was young, and I'm a much better programmer for it.

I'd look at what he's writing over how he communicates it. Perhaps the language might be arrogant or self-congratulatory, but it benefits you more to look at what he's saying than how he says it. (responding to thread here; you obviously didn't make this mistake)

I'm a javascript fan. I think it's a good language and for the most part I enjoy programming in it.

However I am not going to argue that the median javascript user is as smart as the median ocaml user. 99% of people learn javascript because they have to. Most people learn ocaml because they are enthusiasts. They're interested in programming language concepts and becoming more effective.

Why do you think JavaScript is a good language?
I'm a big fan of Javascript. It runs everywhere, is easy to write, is brutally flexible.

I would never call it a "good" language. It is an abomination created by the dev teams at 4 different browser companies over the course of 20 years with no coordination between them.

And the original version was banged out in a very short time period to create a feature. Then everyone else just piled onto it w/o consideration for the consequences.
There is a useful and practical small diamond hidden in the big ball of mud.
Yeah, it's called Lisp.
For those who are downvoting me: Javascript was deliberately invented to be Scheme without the Lisp syntax... Jesus.
Javascript would be amazing with s-expressions and hygienic macros. One of the biggest missed opportunities in our field.
Via the Self programming language. That’s where prototypes come from. Self messages were closures, so JS functions are first class. Smalltalk was considered to be in the spirit of Lisp, and Self replaced classes with prototypes. That or Brendan Eich was mixing several features from expressive languages.
It is wildly flexible, aligned with how programming is taught, and infinitely documented.

It is the swiss army knife of programming. Even top-tier hackers use it as a primary tool. Check out Frida[1], it uses the Chrome v8 engine to inject parasitic tracing code written in JavaScript into any OS (incl. android & ios). There's no language that would have fit the bill like JS+v8.

[1] https://frida.re/

Isn’t V8 written in C++? There’s no reason Python can’t be as much a Swiss Army knife, except that it doesn’t run in the browser, which was just a historical matter that it was JS and not some other language. Tcl was proposed, and Sun tried to get Netscape to run Java natively.
JavaScript is basically a lispy core with Java or C esque syntax and a bunch of features from all other programming languages incorporated over 20 years. It's fast, flexible and easy to learn. Just look at all the things that have been built in JavaScript...
- Relatively expressive

- Relatively fast

- Enormous ecosystem - the "good parts" of which still have practically everything you need

- Top notch typechecker in the form of typescript

There's a good chance you misread it.

I interpreted it at second effort as:

"Pick a language that is famous for being an oddball but that has good credentials, since you have seen that people that to you are worth credit use it".

“Weird sense of superiority” is a very succinct way of describing most of PG’s takes on programming.

I’m reminded of his argument about how “hackers” choose languages that let them type the fewest characters possible, an argument that seems empirically unfounded to me.

> I’m reminded of his argument about how hackers choose languages that let them type the fewest characters possible

Ah yes, just like real writers write in Ithkuil, a language constructed to maximize the meaning encoded per syllable.

Some of PGs arguments against static typing (in hackers and painters, IIRC) were also completely unfounded. It turned out he was confusing static typing with explicitly having to type (keystrokes that is) the type of a variable or parameter. Utterly unaware of type inference.
Static typing and inference aside, I find that his arguments about language verbosity and character count utterly without evidence. A quick review of the startup scene will show a wide mix of programming languages, including a lot of Java.

It’s fine if that’s his preference, but the argument that the best programmers (“hackers” in his parlance) prefer what he prefers to be both self serving and contrary to actual real world evidence.

I wonder how much coding PG does these days. He reminds me of Al Bundy, how Al constantly talks about his highschool football team years as his life's peak, 30 years after the fact.
What is the most impressive programming feat PG ever accomplished? A Lisp dialect maybe?

I sort of get the sense that he doesn't realize how many crazy talented (but not famous) programmers there are out there. He's got a microphone and is determined to keep using it to tell us how great his ideas are, but the audience has gotten a lot more discerning since the 90s when producing a CRUD app in Lisp could still be considered a feat.

There is nothing wrong with admitting that a certain group of people is smarter than another one. I would be very surprised if the members of the group I did my PhD in were not much smarter than the average programmer.
You think hiding behind academic trophys can raise your iq?
No. I am saying that the IQ of academics is higher in the first place. Not in general, but in that group for certain.
So, you think that hunting for academic trophys does not correlate with smartness? And the way to become smarter is cracking an IQ test to gain a high number to be hiding behind?
Richard O'Keefe (2013), erlang-questions mailing list:

    Once upon a time (about 1992ish) in a land where the moles
    have beaks and swim and the deer jump on their hind legs
    (Australia), a certain computer science department (RMIT)
    decided that Pascal had reached its use-by date.  What shall
    we do?  What shall we replace it with?  Set up a committee!

    I was on the committee.  We set up a short list.
     (1) Scheme.
         Tiny language, amazingly capable, REPL so you can try
         things out, implementations for all the machines we
         cared about.  And Rob Hagan at Monash had shown that
         you could teach students more COBOL with one semester
         of Scheme and one semester of COBOL than you could
         with three semesters of COBOL.
     (2) Miranda.
         The commercial precursor of Haskell.
         Melbourne University were also looking at this (or had
         already switched to it) which would make it easier to
         pick up some of their students.
     (3) Ada.
        Close enough to Pascal that our staff were comfortable 
        with it and our material would not need major revision.
        A better Pascal than Pascal.
        Handled concurrency about as nicely as an 
        imperative language can.

    What was the deciding factor?

    Schools.

    Our deliberations leaked, and we started getting phone calls from
    careers masters saying "if you go all theoretical [read: (1) or (2)]
    we'll tell our pupils not to study with you."
http://erlang.org/pipermail/erlang-questions/2013-January/07...

Personally, I'd maybe not apply the adjective "smartness" here, but there is some sense in which some languages have better taste than others, and what drives language popularity is not usually good taste, and I interpret pg here to be saying he prefers to recruit programmers who show good taste in the languages they work with.

My school started everyone with a semester of Scheme, followed by a semester of C.

I don't have any sort of legitimate control group to compare to, and I'm obviously biased as heck, but I do still hold the impression that I and others who learned that way can learn new languages and programming techniques much more quickly than acquaintances who were fed a steady diet of Java or Python. Many of them, even 20 years on, still don't really have a firm grasp of what single dispatch is in the first place, which hinders their ability to use it well. Which is ironic, considering it's all they've ever known.

I agree; I hate the "smart" perception. My guess is that, if there's anything there, it's just the gift of a stronger grasp of the fundamentals. Scheme brings you very close to the abstract foundation of computer science. C brings you very close to the technical foundation of computer engineering. I'd like to think there's a lot of value in starting out by establishing a firm foundation like that.

This is a very nice combination to have for those students who want to go deep into language implementation and its interface with OSes. C is good for understanding how to write VMs, Scheme is great for code transformation.
For reference, this Richard O' Keefe:

Dr. Richard A. O'Keefe is a computer scientist best known for writing the influential book on Prolog programming, The Craft of Prolog.[1] He was a lecturer and researcher at the Department of Computer Science at the University of Otago in Dunedin, New Zealand and concentrates on languages for logic programming and functional programming (including Prolog, Haskell, and Erlang).

https://en.wikipedia.org/wiki/Richard_O%27Keefe

This is both troubling and understanding as someone who has been on both sides.

As a student, we were required to learn assembly in a microcontrollers course. It was a disaster, because it was a very short semester and they were asking we learn microcontrollers and assembly at the same time when most of us could barely program to begin with. I left a review urging they change to C (still low level, but so much easier) and they actually switched the next year.

Learning ASM is indeed important from a theoretical stance (and practical for some jobs), but you can't expect students to just pick that up in a few weeks worth of classes.

Then when I got an office job, I learned a LOT of engineers do process automation programming. At that point I could see even something as hideous as VBA being used to efficiently save hundreds of hours of work.

What do students really need? It depends on a lot of factors. Are they going into academia to study PL theory? Then Lisp, Prolog, C, and Haskell are probably pretty important. Are 95% of your students going into industry? Then Python, C++, Java, C#, JS, Excel, and SQL are all going to be important.

I think the really theoretical stuff (Haskell, Prolog, Lisp) should only be briefly introduced in undergrad and expanded upon in grad school. Or you have specific academic or industry based programs.

> I think the really theoretical stuff (Haskell, Prolog, Lisp) should only be briefly introduced in undergrad and expanded upon in grad school. Or you have specific academic or industry based programs.

My experience is Haskell actually is highly practical for many tasks. So I think it’s misleading to call it “really theoretical”. It’s the reason you see FP in areas as diverse as spam filtering, distributed computing, smart contracts, various financial services, etc.

While less common, there absolutely are areas in industry that do tend to use FP, and I don’t think you should cut students off from easily entering those specialties (or having to plan to enter them ahead of time).

Additionally, there are concepts used in imperative languages which are not as easy to understand or express in those languages, e.g. promises, are more clearly expressed as monads in a language like Haskell.

I think your view of Haskell's use in industry is skewed by HN. Yes there are SOME Haskell jobs, but it's not even in the top 50 languages last I checked (or if it is, it is still far down the list). A student getting a job doing spam filtering in Haskell for FB would be a nearly zero probability event in comparison to something in Java. Just go look for Haskell job postings. I bet it's 0.0001% of something like C#. So when you say uncommon, I see exceedingly rare. Every hour of student time is precious, so a single course covering PL theory in undergrad that introduces the concepts should be plenty. If someone really needs to learn Haskell in industry (a unicorn case), they can do it there. Otherwise the focus should be on practical experience and theory relevant to 95% of computer science and related jobs (object oriented programming, SQL or NoSQL databases, algorithms, web development, networks, operating systems, cloud computing...etc).
> I think your view of Haskell's use in industry is skewed by HN

It’s really funny you say that, I view HN as being frequently anti-FP. I guess when you split the difference everyone is a bit unhappy. In my case I’ve been programming for over 30 years and only on HN for a few months, so I don’t feel like it’s swayed me much, you never know. I’ve read Graham for years and he certainly has been an influence.

Overall Haskell alone isn’t that big in industry, but it most clearly illustrates many FP concepts and is the originating point (or an early adopter) of new tech that makes it into other languages.

If you look at all the jobs in Scala, Haskell, Clojure, F#, OCaml, Elm, Erlang, and PureScript. Then you throw in all the jobs in multi-paradigm languages Python, JS, etc. with managers or coding standards that dictate functional techniques, then subtract the particularly awful soul crushing dead-end jobs (that regardless of paradigm or language) probably none of us want, I think you may be underestimating the representation of FP.

Ultimately when I hire someone with a 4 year degree from a research university, I’m not expecting them to have 100% vocational training, they should be literate in at least a couple languages, but I’m much more interested in knowledge of concepts and adaptability.

The best Python programmer I’ve worked with described his junior year as being almost entirely Standard ML. I think he was better for it.

This is a great quote:

> And Rob Hagan at Monash had shown that you could teach students more COBOL with one semester of Scheme and one semester of COBOL than you could with three semesters of COBOL.

Really makes the point about how studying uncommon languages can pay off.

I've known a great many programmers over many years and I've observed some patterns I'll note below. I'm not hypothesizing on why any of this is and it could be for any number of reasons. However, neither arrogance nor a desire to maximize pretentiousness has struck me as one of them, except for a handful of the most immature persons who quickly grew out of it.

Every single programmer interested in any language in the ML family or Haskell has considerably above average[1] intellectual horsepower. The syntax and type system can both fairly be called "weird."

The Lisp programmers I've encountered are along a wider range. They've ranged from average to ML tier, the latter being the ones that, as PG observes, are more interested in "weird" features like macros, call/cc, and so on.

And then you have extremely popular languages like C, C++, Java, JavaScript, Python, and so on. Virtually every programmer has used one or more of them to a significant degree, so the mean programmer using one of those languages is virtually the same as the mean programmer in the general population. This is expected since in cases like this the mean of a subset approaches the mean of its superset as the size of the latter approaches that of the former. Programmers who master C++'s template system are an exception to the above. They're also well above average.

[1] In this comment everywhere I say average or mean I'm referring to programmers and not the general population. Average isn't bad, the average person here is quite bright for example.

> Every single programmer interested in any language in the ML family or Haskell has considerably above average[1] intellectual horsepower.

Just to point that there's nothing strange or unexpected about this. You will get people that are more intellectual than average it you filter by any niche intellectual activity with no immediate non-intellectual reward.

I mean, if you search for programmers that understand plant physiology, you will get the same effect. It basically means that smart people tend to be curious.

>The Lisp programmers I've encountered are along a wider range. They've ranged from average to ML tier, the latter being the ones that, as PG observes, are more interested in "weird" features like macros, call/cc, and so on.

I'd say that since there's lack of Haskell jobs, then non passionate people do not touch it since it's useless to them

Passionate people check it out cuz other passionate people recommended it

And circle repeats.

Well, the current mode is to select by availability of cheap resumes (majority) or fashion (minority, hip places).

Whik I'm not sure I'd always agree with PG, a recent anecdata I heard was a company selecting for Lisp because picking Python meant wading through mountains of fresh bootcamp grads with (quote) "overblown sense of their own capability" (unquote) - same applied to JS, less so to C#/Java.

(Un)fortunately, the company noticed they didn't have resources to filter that, and decided that by going for "weird but capable" combined with global remote organisation they could filter for people experienced, or willing to experiment with weirder languages. Apparently ithe cost of having to sometimes implement things from scratch was lower than expected.

I'd say it's obviously true and right. And it doesn't require assuming arrogance and pretentiousness.

Niche languages, by definition, are not good investment if you're after a well-paying job. A niche language that requires understanding advanced programming concepts is, by definition, filtering for people who a) can understand those concepts, and b) have a non-monetary reason for doing so, which implies c) they're likely not faking it.

Whether or not such people would be good software engineers is another topic. Software engineering encompasses more skills than just raw programming ability. But a proficiency in advanced niche language plus proficiency in a mainstream language plus some work experience? It's hard to imagine how this would not be a good signal for smarts and skills.

What a strange argument. What I've seen in other fields is that when the people who are clearly smarter than me in those fields (whether by natural ability or by experience and hard work) tend to use different tools than I do it is usually because those tools are better for work in that field. They might also be harder to learn or use, but for those who can learn to use them well they end up being more productive than if they used the tools I am using.

If I see just one smarter than me person using a particular tool for some task that I also do, it might be because they are using it as an intellectual challenge or for variety, but if I see a lot of smarter than me people using it for that task I've almost always found it is worth looking into it seriously to see if I should use it too.

Maybe the following would have been more appropriate?

“Pick a language that most programmers consider weird but whose median user is curious and shows the initiative to explore strange new worlds of how to get things done.”

I consider myself a very capable hack. I am not really very “smart.” But I am motivated to learn more. And to improve the craft of software solutions.

Oh c'mon. There are clearly languages where the median intelligence of the community members is higher than others -- I'm not a Haskell fan myself, but I have to concede that the community around Haskell is very obviously comprised of smarter than average people. Check out their IRC or Slack channel if you have any doubt.
I think it makes sense. For example, Erlang is a kinda weird (to me) language. Back in 2017, I went through a book on Elixir + Phoenix, and then spent some time going through Erlang topics. I mostly spend my day on mobile app and backend programming, in languages like Swift/Kotlin/Javascript/Go.

I believe I learned a lot, and most of the people I encountered on those slacks and forums seemed a lot more experienced and capable. That's also because the language is kind of niche but powerful, so not everyone is starting out their career trying to print Hello World in Erlang. It is a language one would discover when trying to solve a specific problem, in my opinion at least. Therefore, there are less noobs like me and the people I encountered were super helpful and thorough compared to my experience on other languages.

Yup, it feels like my disillusionment with SV and PG are tracking, this is comes across as someone that likes the smell of their own output and wants everyone to know.
I disagree. The quote only mentions that the median user should be smart, which means that you can also learn from them if you are inexperienced.

I also see no pretentiousness. With smart people hundreds of useless discussions are avoided in the first place. If you work in a popular language like Python that attracts all sorts of people, you have 10 preposterous technical and social discussions per day.

I think this essay isn't supposed to be anything comprehensive about Lisp, it's just encouraging his target audience to consider other options.

I understand your sentiment. Back when Coursera first started I took a class where 10 minutes into the first lecture the teacher said something like “This is the basic 3rd year calculus you did in highschool”. This was discouraging because it made a qualifying assumption about both me and my highschool that was far removed from my reality. In the end, that detail had no bearing on the class, and seemed to exist only to humiliate me.

But, many years later, I’ve learned I gain nothing from this kind of defensiveness, and simply keep a running list of things I’m “supposed” to know, but don’t yet. Of course, now that is a small list of very uncommon things, which itself shows how much I’ve progressed.

Point being, digging in your heels only hurts yourself.

In my experience there's a form of stupidity that comes from simply being incurious. Whether someone is interested in exploring languages outside the present set of mainstream imperative languages seems to pretty good indicator of that intellectual curiosity.
But a meta-smart engineer that wants to maximise real world impact through a software project would realise that not all ‘smart’ people agree about what smart ‘IS’.

So for engineering efforts that require large amounts of people to contribute, a more restrictive, less flexible language can yield better overall productivity by expanding the pool of potential contributors and reducing friction arising from pointless differences and ‘smart’ programming (like macros).

In other words, removing ‘smart’ programming features like macros probably turns out to be (weirdly) smart in the real world.

Go is one of my favorite languages exactly for the reason you describe - it focuses on getting things done and it scales to collaborating with many people.

At the same time I enjoy tinkering with different new languages every once in a while and I think that's what the article talks about. There's a place for experimenting and trying out new things, that doesn't mean that you need to rewrite everything in Haskell.

But not having enough abstraction is also problematic and Go does cross that line for me at least.

Eg. on my current CRUD app, we use Spring’s aspects to implement some permission checking before specific HTTP requests. The alternative - copying a function call to each place - would be much more bug prone, a change in one will not be propagated, etc.

While it may not be the best example, there are many similar cases where I feel that less abstraction would just make it unmaintainable.

Smart here is used as an indicator of a language with unique powers. So it's more about what the engineer can do to expand his own mind, to get new perspectives.
But in one sense, there are no languages with unique powers. Ultimately all languages are instructions for a CPU. The language can make you ‘feel’ smart as an individual or ‘be’ smart by allowing a large group of people to accomplish something that couldn’t be achieved by a single person.

My hypothesis is that languages that are good at making the individual feel smart have proven to be less effective at allowing a large group of programmers to collaborate.

Being clever alone or in a group can be different things and valuable in different situations.
Sure, but the article is rather disparaging to the engineer spending their life in the so called ‘mainstream’ 99.5% of languages, implying their work is in someway less ‘smart’ than those exploring the 0.5%.

I am offering a counterpoint that instead, some ‘smart’ engineers have concluded that boring programming languages are the way to get big things done.

This was certainly my experience with Smalltalk in the 1990s. The "good" programmers oustripped the departmental guys so quickly we ended up with two factions in the one company and libraries of code only the gurus understood. It killed the code re-use stats and resulted in a lot of duplicated work.
I think that scenario speaks to the importance of training, regular knowledge sharing sessions, pair programming, and the like. I've found myself in the opposite situation, where the team refuses to use a language feature that will make life significantly easier out of consideration for some hypothetical clueless graduate.

Addressing a skill gap technically seems a bit short sighted compared to addressing it culturally. Especially because most weird language features don't actually require you to be smart to understand them; they're just unfamiliar.

I've been thinking about this a bit, and something like Smalltalk is just completely alien if you came from a C or a Cobol background. The Cobol guys were used to using a rich, transaction based environment and the C guys were used to rolling their own everything. When they hit Smalltalk and the "if" statement looks like...wtf the boolean does the work? Or even better, one of the gurus decided that the best way to solve the "how do I get my database connection information" was to give the users a class that deliberately threw an exception they were meant to catch at the top of the chain of execution. In this case, the guru wrote a class that threw a "#doesNotUnderstand" which can be caught, re-injected with the appropriate object, and the program can continue.

It quite simply was too much for some guys to get their heads around. It probably wasn't the best way to use an exception either, but occasionally when I'm working with .NET I really wish I could catch some of those, re-inject the expected bit of data and have my program continue it's merry way.

One of the modes of working in Smalltalk is to deliberately write something half finished, so when the #doesNotUnderstand gets thrown, you can edit the code during while debugging, accept it, and continue the program. If it takes a long time to reproduce a bug in a C# program, you're stuck with going through all the motions to get back to where the bug exists, but in Smalltalk you could simply fill in the bit of broken code, continue and it would work from then on.

Again - hard to change the habits of a lifetime and I'm not sure that as a long term development environment it's very healthy (you might fix an instance of the bug, but did you fix all the possible combinations of it?)

Still, when you're in a Smalltalk groove it feels like walking a high wire and performing magic.

Except that some languages let you take full advantage of the hardware and some don’t. For example the ability to parallelize code, or write a device driver.
Yes that’s true. Also some don’t even run in a browser for example.
There are different types of problems to be solved.

There are "business as usual" problems, so gluing libraries, CRUD's. Where having junior level code is by far most efficient because you probably have to face multiple issues. Ones like employee rotation, lots of business requests where it is by far better to have code duplication and some tweaks in copy pasted code so it stays simple and don't introduce wrong abstractions. Even generic types as in C# I would consider mostly bad idea to use for those.

Other type would be libraries or frameworks where you definitely cannot afford "copy/paste/change". I would hope that people working on libraries or frameworks stick to what they write for at least 5 years and hope they could be life long supporters. For those people and types of projects you want some smart features like generic types so that they can simply do their job. I cannot think of a framework that would not use quite complex ideas to achieve what it should be.

Of course there are many more like hardware programming, operating systems and the ones that PG pointed as 0.5% of developers work like really hard/weird problems one cannot solve by simply making CRUD.

I have pointed only at things that are in my line of work. Unfortunately there is a lot of people who should be delivering things as in CRUD/glue/junior so the first category. Where what THEY think they should be doing is some kind of framework/libraries work. Because they think that it will make business "future proof" and "that is what professional developers should do", while wasting resources.

Of course doing CRUD/glue in an easy way that can be understood by juniors and fast is important and highly valuable in itself. But I think a lot of people don't understand value of it.

IMO the greatest achievement of collaborative programming so far is Linux. Not a CRUD application written by Junior developers.

And it is written in C, which I assume is not one of PG’s blessed ‘weird’ languages that supposedly superior programmers are using.

Here's what I could write in C that I couldn't in (most) other languages:

  unsigned short *reg = (unsigned short*)0xFFFF1014;
  *reg = 0x1027;
If you have memory-mapped I/O (like the 68000-style architectures did), this lets you take a hardware register at a known address, and write any bit pattern you wanted to it. For embedded hardware, this meant that the hardware was right there, ready to work with.

Sure, you can crash your program if there isn't the hardware you expect at 0xFFFF1014. Sure, you can use this exact approach to trash memory anywhere in your program image. But it lets you easily do things that are not easily done in most other languages.

Very interesting and you’re right that this is almost uniquely and most easily expressible in C, but if that makes C ‘weird’ I don’t understand what the point of the article is anymore.

By that definition all languages are ‘weird’ including Java and have uniquely expressible koans within them.

Maybe it boils down to ‘use the right tool for the job’, ie, the tool that lends itself best to the job at hand.

Yes, weird depends. PG's point is, again, about finding new pockets of programming, not necessarily finding the best tool -- meta or not -- for a task at hand. Fine, everything is binary code in the end; it doesn't mean there aren't different abstractions that can be made on top of it, obviously. You are probably right that PG is biased towards "hacking" rather than team software engineering by him implying that the 99.5% of "glue programming" is boring. There is potential for a lot of mastery on the glue front, but this point about weirdness is about the remaining 0.5% and how to access it via the language route. Personally I'd be interested to hear what PG says about the weirdness of OOP...
I would have to ask you to explain a bit more why is it that - you took from my comment?

I am not writing about one or the other being better, so I would like to see more context from your point of view.

I enumerated problems as I understand those and tried to match proper tools - while thinking that as a lot of businesses pay for CRUD work, they think it is valuable as in monetary value not in some absolute terms of what we can achieve with software development. I don't think solving hard problems that are "0.5%" of development work done in some esoteric language is greatest achievement or best in absolute terms.

> 99.5% of programming consists of gluing together calls to library functions.

First, my own career was not as pathologically skewed as this. I did mostly glued together calls to library functions, but I have done a fair share of algorithmic work, such as parsing and image processing. (And cryptography, though that was mostly done on my free time so I’m not sure that counts). Maybe web dev is like that, but I didn’t do web dev.

Second, this is a huge problem. This means that very few of us actually know how to program. And the problem feeds on itself: if one doesn’t know how to program, it will be easier, more tempting, to take on some significant dependency instead of just implementing the part you need, while tailoring it to your use case. Eventually knowledge is lost.

> Eventually knowledge is lost

There're thousands teams all over the world working on various projects which require people to program. At the very least, someone needs to write and maintain these libraries. Also there're interesting domains like game development, CAD/CAM/CAE, HPC, embedded. Knowledge is transferred within such teams.

Why would it be better for tens of tthousands of people to rewrite the same bit of code over and over again, ? This amount of code reuse sounds excellent to me.
Because then they would learn to write that code. Because it’s not the same exact bit of code, but just a part, or a different version depending on the exact context. Because taking on a dependency is just as costly as rewriting the thing, if not more…

Code reuse is good, but we should not forget that its costs are not nil.

I don't have a background on theory of programming languages or history of CS (I'm EE), correct me if I'm wrong but:

1- I have never seen a language that made me wow. Like, to me, this whole concept of making a digital logic architecture do a task should be "solved" in a systematic/mathematical sense. Yet, whenever I read on criticisms of languages, people always talk about stuff like "Go doesn't have generators", "Rust macro is a mistake", "I don't like python's async story", "C's way of things is outdated" etc...

As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)` notation or whether we should use `t` or `x` in solving a differential equation. Like, we are not solving the actual DE, but complaining about issues irrelevant to the big picture.

2- I have a feeling that https://www.red-lang.org/ is something completely new and innovative.

3- I think concepts like formal-proofs and RTOSes are under-rated.

> As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)` notation or whether we should use `t` or `x` in solving a differential equation

Until you start manipulating the 'dt's on their own which wouldn't occur to you if you were using the dot notation.

(And then some people tell you that it's illegal, or maybe okay but only if you've taken real analysis... it gets confusing)

This is one that blew my mind back in the day, compare these two quicksort implementations: https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#C https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Ha...
The C code implement quicksort, the Haskell code does not. It has different (worse) space characteristics. Proper quicksort in Haskell is not a two-liner.
It's a parlor trick, but a cool one is my point.
But you can make that parlor trick work ok in C too if you even the playing field by implementing a partition() helper separately.

The Haskell version reveals more of a deficiency in the C standard library than the language.

A parlor trick that doesn't implement what it claims to, even if cool, doesn't make a point very well...
A sort is a sort or it isn't a sort? Don't get it. Is the claim that the first quick sort impl. in haskell on rosetta is NOT a quick sort?
Quicksort is a specific algorithm involving two array pointers and swapping values. The haskell implementation in question is not it. It’s not a “claim”, it is what it is.
Is it a parlour trick in lisp or erlang?
Are you familiar with prolog ? For me it was kind of "wow" as it's very different from all other programming languages. I don't use it but it was very interesting to learn it.
About (1)

The first Prolog program I ran just blew my mind - sort of "But how did it do that!?" I understood what I wrote down, and how that explained the problem, but a mental model if how that was used by the runtime to solve the problem needed a while to develop.

Similarly Smalltalk was like: "Everything is an object?". I mean the language doesn't have an "if" statement! You send a code block as a message to a boolean value with an "ifTrue" method.

Not that I know these languages to any significant depth, just dabbling.

To me there are a few oddball languages that are simple, have one abstraction of abstraction and are quite weird, but have a stack record of "heroic deeds" by their practitioners.

I mean C#, Java, C, C++, Go are quite similar if you squint.

But Prolog, Forth, Smalltalk, J, Lisp, etc. are definitely something else that stretches your mind a bit in different directions.

And I think that this is a valid point.

It's worth spending a bit of time reading about and playing with these languages. Not because they are useful (although they might well be), but because they will give you a few different ways of thinking about problems that will extend your mental reach.

I feel the same way about Snobol4. It gave me the same wow factor that Prolog did.
I came to this thread to write about prolog too. it wasn't the first program I wrote, but after a good introduction, then I started thinking the way prolog makes you think, I was blown away. I loved it and I hope I get to use it again!
> Similarly Smalltalk was like: "Everything is an object?". I mean the language doesn't have an "if" statement! You send a code block as a message to a boolean value with an "ifTrue" method.

Incidentally, I don't think that this is how they got there, but this could have come from taking the lambda calculus extremely seriously: in the classical encoding, `true = fst` and `false = snd` (i.e., `true x y = x` and `false x y = y`; or, pointlessly, `true = const` and `false = true id`), so that `if` is just `id`, in the sense that `if true = true` (meaning `if true x y = true x y = x`) and `if false = false` (meaning `if false x y = false x y = y`).

https://en.wikipedia.org/wiki/Lambda_calculus#Logic_and_pred...

> As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)`

The fact that makes all the difference is that informal notations in math, science, linguistics and other fields are interpreted by human brains, human brains are flexible at filling the gaps and deriving most reasonable consequences from their incomplete descriptions. Symbolic notations outside of formal logic and programming are mostly an annotation DSL to augment humans communicating with each other.

In contrast, a programming language imposes itself upon you in a way that those notations don't. You have to describe a lot of things in it. Underspecification leaves too much to the machine, overspecification tortures the poor brains reading after you. The optimal boundary differs depending on the thing being described, might not always exist and sometimes not always that satisfactory (still pisses off the humans or the machines in some parts or another of the program).

Making different programs in different languages and making them somehow all cooperate to describe the same problem opens a whole new can of worms that's just as hard to solve as the original problem. It's nowhere near as hard to mix-and-match mathematical notations (e.g. Lagrangian formulation of classical mechanics where Newtonian dot notation is used to denote time derivatives and Leibnizian fraction notation is used to denote coordinate derivatives). If you're stuck, you can always invent a new notation or whip up a diagram, describe how they work on-the-fly in some shared meta-language, then use it right away anywhere and everywhere you want, including in conjunction with old notations.

So it basically boils down to the capabilities of the underlying machine. The human brain is one hell of a machine, you have a lot of leeway. But programming languages are primarily ways to communicate with a very different type of machine, and as if that wasn't enough they _also_ still have to support wet brains, and as if that wasn't enough they are extremely rigid and heavyweight compared to human notations, i.e. much more difficult and time-consuming to design and implement and spread (when they are new) and de-spread (when they are obsolete and there are better alternatives).

I agree with your statement that concepts like formal-proofs is underrated. Fortunately, one of the general trend that I'm seeing going forward is the birth of programming languages with more and more sophisticated type systems. In these languages type systems do not only capture object types (eg., int, string) but also various other aspects.

For example functional languages and their monadic construct supports capturing various interesting aspects. This allows for really useful feature such as capturing concurrency behaviour (Future/Promise) and possibility of returning errors (Try), at compile time.

Then there's Rust where memory ownership can be reasoned about at compile time.

Languages such as Idris allows to declare a type that is dependent on the value (eg., declare that this function "x() can only return odd numbers?)

I also happen to work in a company where we try to bring type-safety to the databse world with our product TypeDB.

I think this trend is very good to see - stronger type-system = safer code. In a way the stronger type system a programming language has, the more it can validate at compile time. And therefore, we can say that such language somewhat provides what formal proof / formal verification systems ought to provide, but in a practical setting.

> 1- I have never seen a language that made me wow. Like, to me, this whole concept of making a digital logic architecture do a task should be "solved" in a systematic/mathematical sense. Yet, whenever I read on criticisms of languages, people always talk about stuff like "Go doesn't have generators", "Rust macro is a mistake", "I don't like python's async story", "C's way of things is outdated" etc...

Math does have a lot of notations that express the same, but are used for different purpose, where some of those are better suited for solving some task than others. One of the simpler examples is polar vs cartesian coordinates. Where polar coordinates is expressed by angels and distance from a zero point. While cartesian we use the distance on axis from the zero point. Both can express all the same points, but some problems are easier to solve in one of those and some are easier to solve in the other. Coordinate system is definitely not the only place where you have this in math, and it is probably one of the simplest examples.

So math, and all it's different ways of being expressed is more of an example why we need different languages, and that programming languages matter. Than a counterexample of why languages shouldn't matter, and that we are fine with any one language.

> Where polar coordinates is expressed by angels and distance from a zero point.

This is surely the only chance I'll ever have to say "non angeli, sed angli", and by God I'm going to use it.

Err, the angles of our better natures.
The OP doesn't really touch on this aspect, but I think one of the most important traits of a PL is what it doesn't let you say (there's almost nothing that Lisp doesn't let you say, which is a double-edged sword)

A majority of Haskell's innovations have been in the space of placing interesting new kinds of constraints on code

Rust's big innovation is not allowing you to make memory errors (in designated sections of your code)

Go's headlining feature is not allowing people to write code that's extremely abstracted, which helps readability

And this isn't just for avoiding mistakes: code that's very regular can be more easily processed by a machine to make it more efficient

So looking at it through the lens of syntax is missing a lot of the picture. You're right that syntax is rarely important. At the end of the day the differences between code and notation are: 1) code often grows to enormous sizes where managing it becomes a challenge, and 2) code is processed by a machine

> Rust's big innovation is not allowing you to make memory errors (in designated sections of your code)

I’d actually say Rust’s ownership model is its defining feature and big innovation; memory safety without garbage collection was the original goal of the project, but that has arguably actually ended up being more of a side-effect of the ownership model than the actual artefact, from the innovations perspective. Several other languages have been adopting significant ideas from Rust’s ownership model without actually needing it for memory safety.

(Also, some factual clarifications on the wording you used: Rust doesn’t allow you to make memory errors except in areas marked with the “unsafe” keyword—you’re marking small dangerous zones, rather than marking safe zones. But scripting languages are normally memory-safe too, it’s the absence of any garbage collector that makes Rust special there.)

Either way the point stands: Rust’s biggest features are about what you can’t do, not what you can do
(1) F# Type Providers still blow my mind.

Strongly typed SQL/XML/CSV/JSON without boilerplate is a massive leap forward, and it's a shame that it hasn't caught on.

https://fsprojects.github.io/SQLProvider/#Example

Scala experimented with type providers, but it looks abandoned: https://docs.scala-lang.org/overviews/macros/typeproviders.h...

Idris has them (but it's Idris) https://docs.idris-lang.org/en/latest/guides/type-providers-...

This SO answer states that Java has something similar called "Type Manifold" https://stackoverflow.com/a/53037742

I only have F# experience so I can't comment about the ergonomics of the above. I love, love, love the JSON/Regex type providers. I'm trying to move away from SQL (to event sourcing) so haven't used that type provider yet.

(2) Red is just a (worse) REBOL variant, actually.
Can you elaborate on this please? (About it being worse)
I think its more correct to call Red (currently) an incomplete Rebol variant but with loftier ambitions due to its Red/System & toolchain.
1. Read this: https://physicsworld.com/a/how-feynman-diagrams-transformed-...

Main point:

> Theory, Kaiser suggests, is ultimately less important to theorists than the tools that mediate their calculations.

To me, programming languages are almost like Feynman diagrams or chemical notation in that they define how we think or what we think is 'real' in programming. In that sense, we should absolutely care about the fine-grained characteristics of the tools. After all, doesn't a chef prefer a sharp knife to a blunt one?

It's easier to argue about programming languages than it is to argue about things that actually matter[0]. You start to realize that programming languages matter very little the more experience you get programming. Some languages are better suited for one task over another, but there is no objective "best" language.

This isn't to say that the choice of language doesn't matter -- it does. If your team knows C then you probably shouldn't try to start a new project in Java without some ramp-up/learning time. If you're working in JavaScript then you better set aside a lot of time before writing production code in Haskell. These are issues that are more related to people than they are to programming.

The best language is the one that you/your team knows. The second best is the one that suits the task.

[0] https://en.wikipedia.org/wiki/Law_of_triviality

1) Try an array language like J or APL. Or some other paradigm outside the mainstream.
I took a class simply named "Programming Languages" as part of my degree, and we focused on one different language each week for the entire semester.

The only two to make me go "wow" were Lisp and Haskell. They really are that strange and different.

(Well, technically the assembly language we used also made me go "wow," in the sense that I had sympathy for the suffering of programmers in the olden days, but as an EE you may have a different takeaway.)

There are real differences between languages[0], but they tend to be less apparent than the syntactical fluff -- you have to get past the syntax to appreciate the emergent behavior of the language when you are solving a non-trivial problem in it. Also, what set of language features people want is often shaped by historical accident of what they're accustomed to, but also by the problem domain is. It's doubtful that there could be an "ultimate language" that's right for everyone and everything. One of Julia's creators quipped that designing a language isn't just a technical problem, it's also an exercise in applied psychology.

Thanks for point to Red, I'll have to check it out.

Yeah, I agree that it's about time we had more formal methods in software. OTOH, messing around with Dafny has been fun (well, I enjoyed abstract algebra in undergrad), but it takes forever to write anything useful.

[0]https://homepage.cs.uiowa.edu/~jgmorrs/eecs762f19/papers/fel...

I prefer to use languages which have been stable for 20+ years.
Common Lisp, Prolog, APL, Fortran, C, OCaml, Ada.
> And macros are definitely evidence of techniques that go beyond glue programming. For example, solving problems by first writing a language for problems of that type, and then writing your specific application in it.

Is this fundamentally different from "writing your own library to solve a problem, and then using it"?

> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.

Isn't the conclusion here "contribute to/write your own libraries" rather than "pick a weird language"? Or "solve problems from scratch instead of relying on libraries when learning"? I feel like the "weird languages" are shoehorned into a discussion about glue programming vs library programming.

> Isn't the conclusion here "contribute to/write your own libraries"

If you write your own library for a popular language, you're both competing with everyone else who has written a library to do the same thing and picking fights with those who just want tell you to not reinvent the wheel.

The article is mostly about learning. When learning, it's fine to do things people already did. I don't like the expression "reinventing the wheel". I don't know much about engineering, but I think most of our job as developers would be closer to finding a wheel for a specific case, mostly by adapting existing solutions to fit our use case, and sometimes designing a wheel form the ground up.
In serious engineering wheels are reinvented everywhere, but somehow in software you're supposed to use existing parts that do 90% of what you need and then struggle with the remaining 10%.
You can express things with macros that you can not with normal code. But with the advent of decorators and templates that gap has shrunk, and with C++ templates for example. It might almost be possible to do everything with templates that you can do with macros. That code might end up looking weird though.
99.5% of programming isn't actually about the coding at all. It is about breaking down a process to steps small enough to express in code. It is about figuring out what you want the app to do in the first place, and making it meets the goals of the end users. Or, to be more realistic, making it meet the goals that product owners have handed to you on behalf of the end users.

This whole article just feels like it is talking about code for its own sake, which I admit may be intellectually interesting, but has little to do with what we actually do day-to-day when building software.

Maybe that was really the point he was trying to get to - that building software is not the same thing as doing "interesting" code.

I think he meant that

"there exist mental frameworks much more expansive for one's intellectual keyring than conditionals and loops («gluing [...] library functions») - for example «Lisp macros» -, so, «if you want to expand your concept of what programming can be» [presumably to acquire further hold of complexity, and new ways to navigate the solutions space], then explore weird languages with credentials".

Paul Graham’s MO is using language as a startup secret weapon to outmaneuver established companies or lesser rivals (see his earlier writings about Viaweb). Spoiler they used lisp to implement multi tenant online store. He’s talking to startup founders, potential yc applicants. The reality is today, a lot of what they did in lisp is common functionality in every popular web stack out there.

In my view this programming language grand standing hasn’t been compelling for a long time, and now just seems kind of silly. Unless you’re working on really interesting problems, which the vast majority aren’t, judging from recent yc classes.

Yeah it's kind of funny that there was a "controversy" in the very FIRST YC batch, when Reddit switched from Lisp to Python (~15 years ago!)

And there was data that showed that like 90%+ of YC startups use either Ruby (often Rails) and Python, including all the most valuable ones like AirBNB, Stripe, Doordash, etc.

So basically it's been 15 years since Ruby and Python have been acceptable (or even better) Lisps, according to PG's own metrics.

Ruby and Python both have garbage collection, REPLs, and enough reflection/metaprogramming to "compress" your code.

In favor of Lisp I must say that having an image where you replace things instantaneously can be a big plus in exploratory workflows.

Same goes for Smalltalk in this regard.

I like Python a lot but I miss some kind of functionality like that.

I think PG considered competitors hiring Python programers as "dangerous" or something like that.
The irony is that a lot of "very popular" PLs are unergonomic for those 99.5% tasks, and sometimes worse when you take into account "best practices", like testing, documentation, CI/CD, version management (the tax rules will change! But in november for these jurisdictions and September for these jurisdictions ) etc. PLs that are "clever" like pg advocates are often even worse.
Exactly. I don’t really like Java but if I were starting a business that required writing a CRUD backend, I would 100% chose a boring popular language like Java over something “smart”. Smart doesn’t scale - if there’s no tooling, bad library support, and no ecosystem, any gain you get by being clever gets erased by needing to reimplement the wheel. In many ways I’d say the language itself is one of the least important factors in choosing a language for a commercial project.
Java is one of the unergonomic popular languages I'm talking about. I'm never going back to that monstrosity.
...and, then, there are the languages that we need to use, in order to accomplish our tasks.

Most engineers (as opposed to coders) are fairly results-oriented. We may have our differences about how to get the results, or even, what the desired results are; but we always have a deliverable in sight.

It's all about getting satisfactorily-functioning software into the hands of end-users. Put a bow on it. Stick a fork in it. It's done.

Speaking for myself, I write native Apple code (iOS/iPadOS, MacOS, WatchOS, and TVOS). I need to use Swift. I could use ObjC, but Swift is really where it's at, unless I'm doing really low-level stuff. Others may use JavaScript, or even C#, to write Apple software; using hybrid systems.

It is, indeed, mostly "gluing together calls to library functions," but there's a bit of algorithm, mixed in there, as well (not much. Many library functions provide better algorithm support than hand-rolled).

Other platforms have their most effective languages.

I probably could write Apple apps in FORTRAN. I think that there are FORTRAN compilers for Apple systems. I can use existing C or C++ code, to provide "business logic" (I used to run a shop that did just that), so I guess there's a lot of languages that I could use in the backend, and, maybe, some might be better choices, for certain tasks. Again, it needs to be results-driven. If a certain kind of algorithm is most effectively implemented in Lisp, wrapped in system calls, I could embed that in a Swift wrapper.

There's also something to be said for becoming a "native speaker" of a language. That means using it fairly exclusively, over and over again. Step and repeat. I have been writing Swift, almost daily, since the day it was announced, and I still discover new things, almost every day. I think that's pretty cool.

This is stuff that I would never have discovered on a "context switch." I've usually been fairly good at picking up new languages, but I am happy to be sticking with this one, for a while. In the past, I've had to know Pascal, Object Pascal, 68K Assembly, C, C++ (and simplified variants, thereof), and Objective-C, in order to program for Apple (yeah, I've been at it a while).

Agree with you, and Swift is also such a great language. I went from it to Lisp, sometimes I ponder about returning back (however my use case currently is for Lisp).
What are you working on in Lisp, if I may ask?
Mostly text based mathematical analysis. I couldn't stick to Swift as it would rule out a large section of the potential audience (Linux / Win - although Kotlin, which is similar enough, could bridge the gap to some degree), so I'm going more down the Web App route. For now, most of my I/O is in Emacs and later I may plan to work on the GUI side (via Electron or Web App, maybe but very unlikely CAPI or some CFFI).

How about yourself? Do you still do programming in AI?

I do, and I use a Lisp language for almost half of my work.
I agree with you about Swift. I am fascinated by Apple's support for machine learning models as first class components in Swift applications. I have a Swift and SwiftUI app in Apple's store that is really a simple app (short code, written as a nice example for a "Swift AI" book I am writing) that leans heavily on two embedded deep learning models. Really great stuff from Apple.
The problem I had is I learned a bit of LISP - just the basics and then thought “hey this is super powerful - I bet it can elegantly solve some great problems” but then I was stuck! I had no idea what sorts of problems or how to go about it. I guess I’d need to see some motivating examples. The tutorial had a very cool test framework in like 5 or 6 lines of macros so I got a feel for the power but I’d need to see more.

My fear with lisp is that if you use macros it can become obscure what is really going on. Even in C# when I’ve seen metaprogramming done it can kill the discoverability of an app, meaning you have to talk to people who have talked to the person who left the company who knows the mental model. Searching code for keywords no longer helps, or you read the entire codebase to figure out how it works. It was a relief to get off that and work with more familiar CRUD like code. If someone writes a macro, they should write a manual!

I think this is a very valid viewpoint. Typically its better not to learn / use macros until one is sufficiently advanced, functions will do for 99.5% of the circumstances, to call a famous author ;-)

You should try it out. The book Common Lisp Recipes by Edi Weitz is really good and practical - you can get web servers up and running in minutes, and has many other practical uses (I have to check the contents again, but its about 750 pages long and covers stuff like interfacing with C and Java), highly recommended if you want to get productive in Lisp!

> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.

This seems to be true in the same way that "99.5% of cooking consists of making food hot. All popular kitchen appliances are equally good at this." is "true".

Technically you can fry bacon in a pressure cooker, but you shouldn't because we have frying pans.

Scala is a good example of a weird programming language with smart users. The book Hands on Scala Programming is a great way to learn how to express code and think in new ways.

Paul Graham also talks about the power of different programming languages in Beating the Averages, see The Blub Paradox: http://www.paulgraham.com/avg.html

Powerful / weird languages usually aren't the productivity hack you'd hope. A few team members might be more productive with a weird language, but other folks will have trouble understanding their code, so they'll be less productive.

Weird programming languages also require different types of library support (programmers that are passionate about immutability can't use a JSON library that mutates stuff). So they'll build a separate JSON library, but that fractures communities.

It's great to learn about different languages, but programmers seem susceptible to the allure of extra productivity from weird languages and that's not what I've seen.

> but other folks will have trouble understanding their code, so they'll be less productive.

This assumes, you know, that other folks are incapable of learning anything new.

> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.

This is surely the key line here - and the stuff about glue code and median users etc frankly just detracts from it.

It's true in any field. If you want to expand your ways of thinking look for stuff that has been reasonably successful but is outside the mainstream. Put it that way it's sort of obvious but probably easy to forget.

Yes: If you want to become good at something, practice something harder.
Except the point isn’t to practice harder, but to learn harder.
maybe I was not making myself clear: "practice something that is more difficult" is a less ambiguous formulation.
> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.

I'm not sure this is so true. I've glued stuff together in a bunch of languages, and some are easier than others. Particularly in how the package manager works. I'd say c++ throws the weirdest integration issues out of the ones I've used. Rust seems pleasant, nothing too odd thus far for me. Python, super easy so long as you got Anaconda for all the math stuff. JS/npm maybe too easy. Swift/Cocoapods smooth sailing.

But also the languages themselves can make it easier or harder to glue stuff together. If you need to play with pointers and allocators, there's more work to do.

> Weird languages aren't weird by accident. Not the good ones, at least.

No true Scotsman? I'm sure once a language gets more than the initial attention, it can end up a strange mess, just like anything that has a bunch of people tugging at it.

> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages. Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.

I think this is selection at work. Yes, I do consider some coders better than others. But often it's because the kind of person who is good at coding is often the kind who gets to the bottom of things, and part of that is cave diving in weird languages. Probably I rate people higher as coders just from telling me they know Haskell or Lisp, which I perhaps shouldn't (?). But it does appear to me like some of the sharper coders I've met have for some reason been down the Haskell cave, perhaps investigating something to do with the type system.

In my experience of programming so far, the 0.5% thing is signal in 2 basic directions.

It is either that the problem is really hard and so most popular languages haven't attempted a solution and just make do with what they have.

Or, the problem just isn't that interesting. Like, the solution is cool, but applies very rarely and even then doesn't matter all that much. Popular languages could easily implement it, but choose not to.

Apart from the technical benefits of languages like Lisp, OCaml, Haskell, these days one also needs to consider social aspects before one invests too much into a single language.

In terms of influence and earning potential, parochial and closed languages like Python are kind of a pyramid scheme:

The people who were there first occupy many of the top positions in industry, regardless of their contributions or competence. They actively harm and intrigue against dissenters, so be prepared to chant the religion of the day (which the powerful change from time to time).

This sort of thing cannot happen in languages with a standard and multiple implementations like Lisp or C++. Haskell and OCaml seem to be isolated from the most petty forms of intrigue because the average contributors are way smarter and care more about actual technology.

Disappointed. I thought it was about languages such as Lojban /s
u'i xo'o xu la pygy ku jai logji .i pe'i so'i valsi .iku'i na'e logji
> Nor is this all you can do with macros; it's just one region in a space of program-manipulating techniques that even now is far from fully explored.

I like macros. I find myself, not infrequently, thinking about where they would be convenient despite using a language without them.

Nevertheless none of the languages that include them (that I’m aware of) seem very appealing.

Part of this is “program-manipulating techniques”. Less powerful languages are easier for programs to reason statically about, and so usually have great editor refactoring / navigation / static analysis already available. This makes the 99.5% of programming that is mundane more pleasant, and it’s hard to imagine special programs that don’t involve at least a good chunk of this.

The alternative to macros is not never doing metaprogramming, you can do code generation, parse and process the AST, or have program behavior be data-directed at runtime up to including an embedded interpreter. These things are surely less convenient than macros, but it’s a trade off against making all the other parts of the program less convenient to write.

Another issue is most languages with macros are Lisp/Scheme types, and having linked-lists-of-boxed-objects be the default representation for everything often isn’t great for domains that are performance-sensitive (this probably wouldn’t apply to some languages like Nim).

Of course there are the other downsides of using uncommon languages, like often less mature runtimes / library ecosystems.

It seems technically feasible for a language with macros to address all these issues (and maybe Rust does if you’re willing to give up GC). If I was writing a new language I would probably start by compiling to either the JVM/.NET/Go to get a runtime and libraries, and focus on the problem of incremental language extension while maintaining good editor and static analysis support (I think there are some promising approaches for that but this comment is already pretty long).

> Another issue is most languages with macros are Lisp/Scheme types,

Rust, Julia and Zig (if you consider comptime to be a specific type of macros) don't look Lispy to me but all have macros. In Rust I would consider them essential to the language (don't know the others well enough to say), without them Rust would be terribly verbose.

> having linked-lists-of-boxed-objects be the default representation for everything often isn’t great for domains that are performance-sensitive

Disagree, there are extremely performant Lisps out there, including Common Lisp and Chez Scheme. They run as fast as, or faster than, any language that's not a systems-language (C, C++, Rust, Zig).

Julia is a Dylan is a Lisp.
> there are extremely performant Lisps out there

Yes, that’s because CommonLisp also provides native high performance data structures like vectors, arrays and hash tables that complement basic linked lists. Furthermore, most Lisp compilers are pretty mature and create well-optimized x86 code. You can annotate your code with type hints to help and guide the compiler in hot spots of your program.

> Rust, Julia and Zig […] don’t look Lispy to me

Sure, I even mentioned both Nim and Rust (Zig’s comptime is interesting but I wouldn’t put it on the same level). It just seems like most language implementations with macros are Lisp variants (although which ones count as different languages is somewhat fuzzy).

> there are extremely performant Lisps out there, including Common Lisp and Chez Scheme

If you look at for example the benchmarks game [1], Lisp puts in an extremely impressive showing relative to Python/Ruby but often lags slightly Java/C#/Go. But more importantly, the Lisp code is often very non-idiomatic [2], with lots of special annotations and even turning safety features off. Maybe it’s acceptable for optimizing very narrow hot spots, but I wouldn’t want to write a lot of code in this style and wouldn’t expect most third party libraries to be written that way.

I don’t think any of this is the fault of Lisp implementers, but more that the basically default (although not only) data type provides the semantics of dynamically typed linked lists, which are inherently (relatively) slow and tricky to optimize. And even if very clever optimizations exist, relying on them to get adequate performance is less than ideal, since it’s often not obvious where you fall off the fast path. Of course many applications aren’t performance sensitive enough for these sorts of things to matter much, I’m thinking about 3D games etc here where you usually want control of memory layout.

[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

[2] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Maybe you'd be interested in looking at the way Jonathan Blow implemented macros in his programming language.

The video is quite long (and has a Q&A accompanying followup), but I think just the example of creating custom iterators with macros is really interesting.

https://www.youtube.com/watch?v=QX46eLqq1ps

Jai seems pretty interesting, I’m looking forward to trying it out once a public beta is available! Not the least because there’ll hopefully be a fair amount of batteries already included for 3D graphics / math stuff.

In general I really like the approach of designing a language in conjunction with implementing a large project (other than the language itself).

Sort of like how the Hy language (hylang) compiles a Lisp dialect into a Python AST?
Yes, like that! Or like Clojure. If I was targeting the JVM or CLR I’d probably use bytecode, or for Go I’d just generate ordinary source code to feed into the compiler.

It sounds a little ungainly but parsing shouldn’t be a big percent of compile times, so the overhead shouldn’t be that big. And it addresses two of the biggest issues, libraries and (current and future) platform support, things that new language adopters should legitimately be concerned about.

A lot of the most popular mobile games actually now use a similar technology. The game engine Unity converts the bytecode for game C# scripts to C++ which it can feed into the system toolchain. Even as a billion dollar company they decided it was more practical to piggyback on another language for platform support (in their case game consoles, which come with their own C++ compiler but may not be supported out of the box by other language toolchains).

I find synchronous languages like Esterel, Céu, or Blech both weird and eye opening. I created a DSL for Swift (called Pappe) to bring some of the ideas to a more mainstream language.
> 99.5% of programming

Pulling numbers out of thin air like this to support an argument is counterproductive. This should read “Most of programming”, unless there’s research that can corroborate the number.

I think this is a common type of hyperbole and 99.5% of people who read it will understand it isn’t intended to be taken literally.
That is the number one reason why I have tried languages like Lisp, Haskell or Smalltalk. Even Prolog.

You change your mindset in different ways in each of them. When you come back to your usual tool you expanded your thinking to what you could not conceive previously.

Wouldn't you want a pl that makes that makes your 95% glue code easy to write, easy to code review, easy to debug in anger?

Stuff like "make this gql query, but with account spelled 'akkounte' b/c it's in language X, compute and add tax, then depending on the associated customer's SAAS, maybe stuff it into a REST call that has the account and tax as a CSV.

Or: convert this list of integers into f64, take the running average with a window of 5 entries (unless there's a holiday that week) then shove it into this C function that someone else wrote

I am extremely disappointed that the only example of a "weird language" is Lisp. These days — with Clojure, Common Lisp, Racket, Guile, Emacs Lisp, Chez Scheme, Fennel, etc. etc. — Lisp is hardly weird.

I'd love to see an expanded version of this article written by someone less focused on Lisp advocacy than Paul Graham seems to be.

I agree. Lisp should be considered one of the most successful languages ever invented given the number of descendants it has sprout, as you mention. It's not a weird language at all.

Incredible projects like Guix, Emacs and Datomic are proof that Lisp is still alive and well and can create great things.

I would give Prolog or maybe Forth as examples of weird language that still have a "smart userbase".

Ummmm sorry to burst your bubble, all those languages you mentioned are considered part of the lisp family (I'm not sure what Fennel is, so can't comment), so actually you interpreted Paul's statement incorrectly - he didn't say Common Lisp or Scheme in particular, he said Lisp so was referring to all of them.

For what its worth, he's writing his own Lisps (Bel, Arc), is highly proficient in Scheme (just check out the book On Lisp), and is a true lisp polygot. I can't speak for him obviously but I don't think he has a super strong affiliation _just_ to Common Lisp.

This is a line that resonates with me, and the one which some negative comments might overlook (3 hours in, at least):

  "What can you say in this language that would 
  be impossibly inconvenient to say in others? 
  In the process of learning how to say things 
  you couldn't previously say, you'll probably 
  be learning how to think things you couldn't 
  previously think."
This is one of the value propositions of language. It's one of the ways we learn new things, and thus become more capable of doing valuable work as people.

Criticisms of this essay in comments so far have seemed to fall into these buckets:

  1. Lisp? Macros? Boo. (Not novel/too weird/etc)

  2. Languages are solved, not important; I build systems.

  3. I don't like the tone of this essay.
(1) and (3) are side points, unrelated to thesis. (2) is the interesting one, and at the heart of what the essay talks about.

I've always been in the pg camp on this one. Sure, systems are the thing, we can't be purists, etc -- but saying that languages don't matter, for us, would be like rocket engineers saying that materials don't matter.

If you're building a table, you can make it out of almost anything; a table is a solved problem. Wood, carbon fiber, steel.

But at the limits of what's possible, like a rocket, the material's properties, limitations, and weaknesses in extreme circumstances matter.

You can definitely imagine that important things are happening, in the maker's mind, when they start working with a new material, seeing what others are able to do with it, seeing how the making process is easier, or what steps are unimportant/unnecessary now vs. in their usual materials. And that informs their thinking, going forward, about what's possible in systems they might build.

> Languages are solved, not important; I build systems.

This argument always gets funny when sufficiently complicated systems start themselves looking like languages (and their implementations).

I'm not sure it's getting funny. I find it's getting interesting. If the best mechanisms the developers could find to solve a certain problem could be implemented in a language + compiler, does this mean the project should be implemented in this language is? What does this even mean? Maybe it already is implemented in this language? Or is it not, because of the missing syntactic abstraction?

The thought I have related to this is that languages are much like GUIs in this regard. They enable a certain process using some built-in features, but it's next to impossible to abstract over those feature to optimize further.

And I think that is why I stay with a simple language that gives arrays, structs, and function calls - basically tools to manipulate data / memory, I'm not sure that more features are all that useful to write "well-compressed" programs (but I can imagine that it's often hard to see why certain useful seeming features will be detrimental down the road).

I think the feeling a lot of people have – or at least the one I have – is just tiredness of al the churn. This year all tables need to be in wood, but in two years wooden tables are soooo old, what kind of old coot are you for using wooden tables?! Is there something wrong with you?! All Real Programmers™ exclusively use steel tables now!

Two years down the line people start to realize that steel actually isn't perfect either. But wait, now someone made a carbon fibre table and we need to break down all our steel tables and burn the few wooden tables left and rebuild it all in carbon fibre! It's the future, after all!

Of course, eventually people figure out that wooden tables are actually quite good for a fair number of use cases and we've come full circle.

I'm just tired of the churn-and-hype cycle and suspect a lot of people have roughly similar feelings, which is expressed in the "languages are unimportant; I build systems"-sentiment. Less and less of modern software development seems to be about actually building interesting things to solve real problems.

I'd agree that it's a totally valid sentiment in our industry. In the specific context of an essay on pg's site though -- look at those graphics! :D This seems to me like a dude who is okay with wooden tables.
In my experience, the churn is on the systems side, not languages side. The churn happens because someone makes a marginal improvement on some API and makes a nicer marketing copy, and boom, the new most popular JavaScript framework/bundler for this year is born.

Programming languages don't churn nearly as fast (and some degree of existing churn can be attributed to the business model of a PL funded by a company - they have every incentive to push it, no matter how little improvements or different concepts the language brings.)

I resonate with this. The churn I find most demoralizing is in the library/module/component space.

I’ve been pushing myself to learn elixir these last few months. This is, by the comments of many, more of a niche language. I like the language’s novelty and it has caused me to think in new ways. So Paul is righ in this pint.

But when I want to send an http request, there must be at least 10 choices on hex to choose from. The one that is a hit this year will be passe’ next year. When I watch the traffic in the Phoenix slack channel, the “stack” of libraries combined seems overwhelming. The same goes for people talking about front end apps.

You hit a nerve there - our company has gone through 4 "choice" http client libraries in the past 4 years. (We're a JS/TS environment). axios, request, superagent, fetch.
Just curious, why not use OTP's built-in httpc? https://erlang.org/doc/man/httpc.html
httpc is good for a one off request, but it is not very up-to-date with the latest features of the web. So building application logic on top of it is not ideal.
Churn and choice are what keeps me on the fence with Elixir too. Over the last few years I went from very excited and built a few things with it to "maybe try again later".

It's just not fun to be in a constant state of package fatigue, especially when a lot of semi-popular libraries are maintained by 1 person. If that 1 person leaves that entire bit of functionality becomes a liability to your application because it's unrealistically demanding to be a solo developer or small team and be responsible to maintain a bunch of libraries that become unmaintained but then also build your application.

This is IMO especially true with a language as powerful as Elixir with macros. Picking up and reading someone else's code can either feel natural or be really hard, to the point where looking at it doesn't feel like the language you know. This makes it doubly hard to read 3rd party library code because you're learning the other person's code and have to mentally deconstruct a lot of advanced patterns if they use them. I don't consider myself that good of a programmer but there's a lot of times where in Elixir, phrases like "this is impossible for me to understand" come up when I've written hundreds of thousands of lines of code in Python but never thought this. I sometimes had the "what am I looking at?" feeling with Ruby too btw.

As for library availability, this is a problem that doesn't come up as often with more main stream web frameworks, at least not in the Python and Ruby eco-system. Sure things go in and out of fashion but both languages have frameworks that include more batteries included or the community has gotten so big that there's a bunch of independently developed libraries that most of the community got behind and supports it so well that it becomes a no-brainer to use it.

So that's what keeps me on the fence and I think some of these problems can be solved with time, but time is a scary thing because waiting a few years feels like an eternity and the outcome after waiting a few years might be waiting a few more years. At some point you need to build whatever you're building and run with it without looking back.

But I think this really comes down to personal preference. I used to think I wanted unlimited choice and an endless world of possibilities. I don't. I want to build web applications quickly using the most straight forward code I can think of and get as many batteries as included as possible while leaning on / contributing back to a massive eco-system. I don't want to be on the front lines of building a new eco-system. I still do think in the very long term (5+ years maybe) Elixir could be a good match for me once there's a lot of libraries that have hit critical mass.

There's plenty of people using it successfully now, and I'm happy there are people who like being closer to early adopters and setting up the initial ground work for an eco-system.

As someone who just started learning Elixir, this comment makes me anxious. I don't think I am going to write some exotic web application or some unique functionality, but at the same time I also don't want to be constantly fighting with the limitations of the stack I choose.

Is it a mistake to spend time learning Elixir?

No. I'd say even if you don't end up using it in your day to day, learning elixir/Erlang and reading Armstrong's thesis are some of the best things you can do for yourself in terms of "system design/programming enlightenment".
Elixir is an involving platform and community. Think about the Ruby community from years ago, a lot of things are missing, but there is a lot of potentials as well. From my side, I started to see Elixir seriously 5 years ago when I need to maintain a big SaaS rails codebase, and in order to support the increasing quantity of users, I need to throw more powerful and expensive machines, and it was hurting us at that time, and after some POCs, we perceived that it would be really interesting to rewrite some parts of our application in Elixir with Phoenix. I think that it's an important tool to have at hand, something that you can reach if needed.
I wouldn't say it's limiting in the sense you can't create certain things with it. You just need to be very prepared to maybe make more choices and also write a lot more libraries that you could potentially find in Python or Ruby.

It also depends on the app you're building. For me I was building a very large app (a video course platform with multiple payment gateways). One limitation I came across with Elixir is there's no official SDKs for Stripe, PayPal, Braintree or Paddle but there are SDKs for most other popular languages. So if you plan to interface with a number of APIs, chances are you're not going to find an official client for Elixir unless the company happens to be using Elixir or are happy to support it (such as Mux).

It could be challenging and time consuming to have to write both your app level features and the underlying libraries. If your goal is to get a web app launched quickly to test it out and you already have experience with Python, Ruby, Node or PHP it's kind of a hard sell to use Elixir. It's mainly because other languages have way more community libraries and frameworks available that cover common web feature use cases. Plus there's a lot more community resources around blog posts, videos, books, courses, etc..

There's also an interesting divide right now in Phoenix around using Live View or not and if you go down the LV route there's very few resources beyond the docs, especially now with LV 0.16 coming out which completely changed the templating system and how components work. It still feels like it's in a pre-1.0 (because it is :D) semi-experimental state. As far as I know there's also no really big success stories with LV. I don't know of any big sites who are using it all-in to drive the entire navigation of their site and all routes.

The above continues to fall in line with my overall feeling of having choice fatigue with Elixir.

With that said if you're interested in it, maybe try to put together a proof concept that focuses on the hardest part of your app and if it works, make a judgment call based on your personal experience. It's possible you'll have better luck than I did. Programming language selection is a very personal choice, especially when you get past libraries choices and start writing code. If Elixir clicks enough for you at a fundamental level maybe it'll be a better choice even if it means having to write more libraries.

It’s not just how many variations of a given component there are, it’s all the many components I have to become aware of to use, each written by a different author with possibly diffeeent idioms, with varying degrees of interoperability. One has to have an http package, an auth package, a json package, a structure modeling package, the list just goes on and on and on. And so many are often derivative dependencies. It’s not just elixir.

When I look for help in the Kotlin slack, the responses are just a firehouse of “you need Zanzibar, no Algolly, try Firetruck, do Conduct, you might want xWyze…”

All the passé options still work fine :)

But yes. It's true http clients have churned quite a bit. Other things are settling better, for instance Ecto, Phoenix, Jason are very popular and stable.

I think this is also why a lot of older programmers (or even older workers in general) get mistakenly labelled as "resistant to change". It's not that we're unwilling to learn new things, quite the contrary. It's that we've been to enough rodeos to see that many "new" solutions are either pure hype or repackaged versions of stuff that was already tried and found lacking.
I believe this label is less likely to apply to an older programmer if instead of grumbling they were willing or able to clearly communicate problems and consequences of “new” solutions. They would be labeled “old wizards” instead :)
There's some truth to that, but I don't think better communication would really change anything, beyond a few minor victories here and there.

So much of the fetishization of everything "new" comes from a combination of wishful thinking and mental laziness. Especially in larger organizations where decisions are made far from where the work is actually done, there is a tendency to think we can solve problems simply by embracing the newest management fad, enterprise software, etc. It's kind of like the way people think they can get organized "if only they had the right trendy organizer or todo app".

I get the impulse, we desperately want to believe that our hard problems can easily be solved by just changing one thing or buying something. This is the crux of most modern marketing, in fact. Unhappy happy with something hard, just by product or service X.

Older workers tend to know better than others that hard things are hard and that layering some shiny new tool or framework on top of crappy process or a broken business model will not change anything. But saying that out loud, even tactfully, is a very inconvenient truth that will make most managers resent you, and probably label you "resistant to change".

In my experience more often than not, the people the people that accuse others of unclear communication are making an effort into not understanding the message.

But then, I'm not known for fighting against new solutions either, so that experience is probably in a disjoint population. Anyway, I imagine you say that from the position of an "old wizard", but that position is as dependent on a receptive audience as it is on a communicative "wizard".

IF there is a lot of churn you will need to do a lot of communicating, but obviously some times the new will succeed, as time goes by with all the churn and all the poor decisions you would get glum at the prospect at communicating yet again why you think a new solution is not preferable.

I don't actually care though, just I can see this possibility.

They do. It's the nature of new programmers to be prone to hype and marketing and not understand those "clearly communicated problems and consequences" as anything but grumbling.
They’re grumbling because they’ve been there done that, too — tried to communicate the ills of frivolous changes — and nobody was interested in paying attention.
I think we are on the same page that communications are a two-way street. There must be mutual desire to listen carefully and to speak clearly.

My comment above focuses on what the stoics advised to focus on - the things one is in control of changing. In our case, old wizards could control their attitude.

It is a fashion industry, and so it follows that when everyone has wooden tables you need to sell them a reason to stay in business, repairing wooden tables isn't enough.
Yup. The ugly truth is that there are too many programmers writing too much code. It's like the idea of too many lawyers (possibly true?) but way worse. Because, of course, we can produce infinite wood and steel and carbon fibre tables at will at the press of a button.
Re: 2nd sentence : How do you come to this conclusion?
Oh, I am a lawyer. I was more recognizing the cliche here, and maybe that was sort of flip. I would say it's probably more like, "a lot of good lawyer brains are wasted on generally pointless this-big-ass-company v. that-big-ass-company disputes."
> What can you say in this language that would be impossibly inconvenient to say in others?

Maybe it's just me and my possibly-unreasonable infatuation with the Sapir-Whorf hypothesis (SWH) but I've come to think it also applies to many things in life, PLs especially so. "Weird languages" aren't valuable because you can deploy it in production, rather because it will help you recontextualize a problem (in SWH-parlance, it helps you see the world differently).

You can also say, SWH is an academic formulation of the beloved programmer motto "When all you have is a hammer, everything looks like a nail". If all you know is an imperative syntax, all problems look solvable by breaking them down into a series of steps/procedures.

In my almost ten years in the industry, there's exactly one time I was able to apply an "unusual" paradigm to solve a problem. GvR might curse me because I sort of made a Lisp-like DSL in Python but I stand by my design decision. The end-result was a small (~200LoC linted with black) DSL parser with some DB access and a lot of rules which actually tried to solve the problem. When I found something wrong I just had to reformulate a rule, not actually wrangle with loops, conditionals, and control flow in order to rewrite logic.

Honest negatives: I had to turn over the project to someone whose background is in EEE, not CS, and I had to explain Higher-Order Functions to them. Not ideal! Actually, in fairness, I bet most in that team would have a hard time figuring it out because, hey, I made a Lisp in Python! But I still stand by my decision; it was the best for the problem given the resources and time I had.

On the other side of the ledger, the Sapir-Whorf hypothesis is widely considered discredited by linguists.
Has it? I'm genuinely curious to know. "Widely considered discredited" sounds like it's met the same fate as ether or alchemy.

I commented on SWH a few months ago in HN too when another user, claiming background in linguistics, replied that it factors in your world view but not as huge a factor as other cultural considerations. That sounded reasonable.

So as of the last time I looked up SWH (a few months ago), my knowledge of its consensus is that:

- the weak form ("relativism") is true to a certain extent, and definitely not to the extent Whorf originally proposed.

- the strong form ("determinism") is largely debated and, personally, I think it's indefensible as a thesis.

When I took linguistics classes in school it was summarily brushed off, but here's how Wikipedia summarizes:

> The strong version, or linguistic determinism, says that language determines thought and that linguistic categories limit and determine cognitive categories. This version is generally agreed to be false by modern linguists.

> The weak version says that linguistic categories and usage only influence thought and decisions. Research on weaker forms has produced positive empirical evidence for a relationship.

Well, DUH! Did anybody put forward the first version which sounds like a strawman?

"language determines thought and that linguistic categories limit and determine cognitive categories. This version is generally agreed to be false by modern linguists"

The use of words like "determine" appears to make it look bogus. Whereas "influences" basically means the same thing (in practical terms, strongly influences is just as good as determines).

Well, based on my own introspection, the strong version looks obviously true to me - so I'm glad someone took time to disprove it.

When I read the description, I understand "determines" as in, your thoughts internally work in terms of language processing, so their complexity is limited to the complexity of the language(s) you know. It sounds plausible, but also testable by checking if humans who never learned a language with complex grammar are capable of processing complex concepts.

For a long time in human history people did not accept the existence of negative numbers; a Greek mathematician couldn't solve x+1=0 for example (this one also has "zero" in it, which also did not exist for some mathematicians). This seems like a decent example for linguistic categories limiting the thinkable categories. Other Greek examples: Zeno's paradoxes, irrational numbers, ...
>This seems like a decent example for linguistic categories limiting the thinkable categories.

As in absolutely limiting them, though? Like the Ancient Greeks, those who invented zero, didn't have it previously in their language, and couldn't do zero-based equations before either.

Seems like a bad one. New concepts are given new names, or borrowed names, when they’re introduced. The first guy to come up with zero didn’t speak a language with a word for zero at the time.
>I'm glad someone took time to disprove it

What do you think "disprove" means in this context though?

E.g. do you think they really settled anything, the way we can prove a math theorem or verify some physical theory to hold (as a predictive model) to the nth degree of precision?

>When I read the description, I understand "determines" as in, your thoughts internally work in terms of language processing, so their complexity is limited to the complexity of the language(s) you know.

That would mean that developing further language is impossible or even that developing the first languages would be impossible - as those nearly language-less peoples have no means to develop those more complex later concepts.

It's not like e.g. Europeans (let's take them as a model of "advanced" language) emerged in nature in fully formed ancient Greek, Latin, English, French, etc.

They started with the same or even more "constrained" languages (verbally and conceptually) as any primitive people, and - going back to our forefathers - even language-less.

> What do you think "disprove" means in this context though?

What it means for every scientific hypothesis: it takes infinite amount of evidence to positively prove it, but it takes one counterexample to kill it. +/- the usual uncertainty caveats.

> That would mean that developing further language is impossible or even that developing the first languages would be impossible

Not necessarily. It would mean that you can't think about some concepts without first extending the language to support them. Languages still could be extended piece by piece.

>What it means for every scientific hypothesis: it takes infinite amount of evidence to positively prove it, but it takes one counterexample to kill it. +/- the usual uncertainty caveats.

Only in such soft sciences you can "prove" any number of competing hypothesis, and have fractions arguing about them for decades or centuries. And whether a "counter example" is valid and "kills" a theory, will be a matter of interpretation and endlessly debated as well.

>It would mean that you can't think about some concepts without first extending the language to support them. Languages still could be extended piece by piece.

If you can always extend a language to new concepts, the language is not limiting in the strong SWH sense. If it was it would be impossible to reach those concepts from a reduced set of concepts.

> Only in such soft sciences you can "prove" any number of competing hypothesis, and have fractions arguing about them for decades or centuries.

It took millennia for spontaneous generation to be definitively disproven.

That's exactly my point, as that was before we settled on the scientific method.

So this might have been relatedto biology (or in other domains physics, chemistry, and so on), but the matter was debated in the soft sciences way, not in the way we do biology in the 20th century.

It was actually a few hundred years after the modern scientific method because scientists attempting to apply the method failed to spot confounding factors and interpreted their results incorrectly, something I think is hardly impossible even today in even the hardest of supposed hard sciences.
> Well, DUH! Did anybody put forward the first version which sounds like a strawman?

A lot of proto-linguistic (I say proto because linguistics want a real discipline yet) thought in the '50s-'60s did actually believe this. It was the informal basis for teaching lots of colonized peoples Western languages. It was the basis for the book 1984's Newspeak. It was also the hypothesis that motivated the creation of the Loglan (predecessor to the more well known, but still obscure, language Lojban) language. That you find this to be a strawman argument is a good testament to how widespread the knowledge of its disproval has become.

N.B. I also think in the pop programming language world (e.g. Twitter rants) that a lot of folks genuinely believe something similar to Strong Sapir-Whorf, at least as applied to programming languages.

Having actually worked with James Cooke Brown on Loglan (I wrote the first Yacc grammar for it), I have to say my recollection is that Jim's view was more tentative and nuanced than you've made it sound. While we certainly enjoyed finding things that seemed easier to say in Loglan than English, I don't recall him ever suggesting that there might be a thought that a non-Loglan speaker couldn't think.

I think it would be fairer to say that he was convinced that Whorfian effects were strong enough that there would be value in engineering a language to take advantage of them. But while value is somewhat in the eye of the beholder, I would say this hypothesis has not held up well either.

Thanks. My understanding was that Loglan was simply a mechanism to play around with the Sapir-Whorf theory among humans, but thanks for the additional context/correction.
Alchemy is a bit more reasonable.

Even the weak version falls apart under scrutiny. Here's a nice example of this: https://cpb-us-w2.wpmucdn.com/web.sas.upenn.edu/dist/4/81/fi...

This is a good example of a case where there was a phenomenon (a language prominently using non-speaker-oriented direction terms, and correlations with real-world behaviour of speakers of that language) which seemed to support a weak version of SW, but it turns that seemingly supporting evidence was really just a by-product of the testing environment.

I'm not sure how the study you linked is an indictment of the weak version. It seems to fall well under my understanding of the consensus that the weak version is only true to a certain extent and definitely not to the extent Sapir and Whorf originally claimed.

So this does present an interesting result, and one that (AFAICT---I am not a linguist by training) does run counter to the claims of SWH but, more importantly, the study is limited only to spatial reasoning. Surely there are more areas of thought than that?

The study shows that differences in systems of direction words doesn't really affect spatial reasoning.

Yes, this one study doesn't disprove every aspect of SWH, but it's a good example of how SWH claims, even in the weaker versions, tend to fare when subject to more rigorous investigation & analysis.

What area of thought do you think provides good evidence for (some version of) the SWH?

Given that language is also created or modified by people in order to get their ideas across, wouldn’t it make sense if one can have thoughts arise that don’t fit into language but then they cannot be shared without the creation of appropriate language. I often have the experience of having ideas that I have in a sort of mathematical reasoning space (this here makes that there impossible) that I have to translate into English. (Eg If the the call is routed at the IP layer then they can’t reach this no matter what DNS they have access to)
People do, of course, create new vocabulary, but that's not modifying language on a deep level. And, in part that's a convenience: even when you don't have a "word" for something, you can generally describe it. But if it's something you're going to refer to frequently having a nice lexical entry for it is more convenient. We have memory limitations, so sometimes having convenient handles can free up resources.

And your example, I think, also speaks to the point: you're able to reason in mathematical ways; being a speaker of English doesn't block this, even though English perhaps doesn't offer convenient vocabulary for this in all cases.

Only an extremely strong version of the hypothesis is discredited, and that's because humans can create new languages to help their thoughts. But that's not an argument for a single static language being sufficient.
On the other hand, it's not like linguists are doing exactly a hard science, and their discrediting something means much, especially when it touches totally unrelated domains like psychology and neuroscience.
If we want to take this into a more concrete and measurable realm, every programming language is going to get converted into the same machine code before it is run, so it is quite untrue that there is any idea that "cannot be expressed" in one programming language but can be expressed in another. It may be more or less convenient to do but nothing like the strong Sapir-Whorf hypothesis for human languages.
Well, in programming yes.

Though even in programming, there are e.g. non turing complete languages (e.g. simple regex languages), languages without certain high level facilities (making it much harder to organize your code in terms of certain concepts - analogous to organizing your thinking of the world around certain concepts -, which is a SWH-like effect), languages that can't express e.g. infinite loops and are certain to terminate (used e.g. for business logic, templating, etc), and so on.

Even if it all goes down to assembly, a language like Cobol might it much harder to write e.g. a 3D game. And that can be enough for games not be written in that language - it doesn't have to be impossible, just hard, which is enough to discourage most, aside from a few weirdos writing games in Cobol and compilers in bash.

Sometimes, when it's a field well outside of your area of expertise, not making pronouncements can save embarrassment later on.
My sentiments exactly (only on the other side).

You seem to respect everything labeled academic, but not all "areas of expertise" and not all "fields" are equally valid -- and surely not just because they are taught in universities, written about in "peer reviewed" journals, and so on.

Linguistics is closer to soft sciences than the opposite.

> You seem to respect everything labeled academic,

I assure you, I really don't.

> but not all "areas of expertise" and not all "fields" are equally valid -- and surely not just because they are taught in universities, written about in "peer reviewed" journals, and so on.

Fully agreed.

> Linguistics is closer to soft sciences than the opposite.

"Linguistics" spans a range of things from the humanities to the 'soft' sciences (in the sense that psychology and cognitive studies 'soft' sciences) to logic/maths.

Declarativeness targeting a specific problem is definitely good, but it is implementable in any language.
You have touched on what is both the best and the worst thing about programming languages in 2021.

On the one hand, most modern languages are powerful enough that you can build whatever you want on them. DSLs, constraint solving, pure FP, CPS, logic programming, whatever you like.

On the other hand, languages are subject to network effects. If you build an FP system on top of Python and I build one on top of Ruby, the resulting “FP frameworks” will be almost entirely incompatible. That makes it hard for people coming to either of our projects to “pick it up."

It’s great fun to implement your own library or framework that in turn implements something interesting, but everyone doing that leads to applications that are built on top of in-house home-grown greenspunned code bases.

In most production situations, it’s better to find the language and framework that already cater to the idiom you like, and come with a community of like-minded programmers who are familiar with how things work.

Network effects matter at scale, even if they’re irrelevant for a passion project.

The notion that any language can be coerced into supporting any programming idiom is true in theory, “But the difference between theory and practice is narrower in theory, than it is in practice.”

So I suggest there is still a lot of value in selecting the language/framework/library that was built to do the thing we want, right off the bat, and comes trailing a community and ecosystem around it.

what if you want to do more than one thing? Thus is a common requirement.
Lisp Macros making DSLs have similar issues, your DSL doesn't work with the other guy's DSL trying to solve a similar issue.
Sure, you can always implement a Lisp compiler in Java.
Please tel us more - a DSL in python is ... fun ... and having a real world use is cherry on top
Flattered by your interest but now I'm afraid the words "DSL" and "Lisp-like" might've given the impression of far more complexity than the project actually was. Keep in mind the core engine is ~200LoC. Maybe twice that at most. But really, there were far more rules than engine logic in the end.

The project was started for legal compliance so I don't want to go into specifics in case I make a slip one way or another. It did not run in the production cluster per se but was important nonetheless. (Actually, gods forbid it run in production!)

Very vaguely, it simplified structured data. A rule is recursively defined, base cases being simple rules that just returned primitive data. The original data could be an object with deep properties but most rules just simplified it to one with less fields.

I call it "Lisp-like" because after writing a handful of recursive rules, I had flashbacks of when I studied (actually) Scheme in uni. The tree-structure and meta-rules certainly gave that impression. I did not parse parens though, rather the rule syntax is JSON dictionaries. I hope this aided in readability---it should be self-explanatory what each rule did---and so my team did not find it too esoteric.

I don't remember the exact volume of data we processed but it was in the tens of GB, if not low hundreds. We parallelized it and had maybe 20 runners working concurrently. You can claim mapreduce (ha!) at this approach but honestly I think we could've parallelized it as easily if I did not go with this DSL-approach. :)

Immutable record types as the default, most-used way of modeling data is a great idea that some languages cater to and other languages force you to do in weird, hacky ways.

Countless systems have been designed around mutable data simply because they were written in languages where mutable data was the default. I personally worked on several Java systems where mutability was used but was trivial to refactor out, because every place an instance was modified, it was simple to construct a new instance instead. On a couple of them I had ownership of the codebase and was able to complete this refactoring with a reasonable amount of effort.

I also created a small codebase in Java with an immutable data model, only to pass it off to someone who immediately added setters for every field because they were "missing." And then of course he started to find uses for them.

I don't have a desire to work in Java again, but I think Java recognizing immutable record classes as a concept worthwhile of first class language support is a significant step forward for the industry.

> Actually, in fairness, I bet most in that team would have a hard time figuring it out because, hey, I made a Lisp in Python! But I still stand by my decision; it was the best for the problem given the resources and time I had.

Are you completely sure you didn’t just create a massive headache for the team that followed you? Now they have to understand something that looks like magic, or pay more money to hire a wizard.

I’ve seen a lot of “clever and elegant” solutions that become instant legacy when the original genius leaves, and a lot of “boring and repetitive” solutions that stand the rest of time.

I feel like the bit you quoted already captures what I think came of it after I turned it over. It is even from a paragraph labeled "Honest negatives".

Complete certainty of how it turned out is a bit too much to ask. For every story like mine, there's an equivalent story of a legacy system in boring Java/C that no one wants to touch, works like magic, etc.

FWIW, I wrote a pretty extensive documentation of the project before I left, including recommendations for improvement[1]. Again, it's foolish to claim complete certainty but the nature of the project was such that they are unlikely to need to rewrite anything on top of the engine. Any modifications and additions moving forward would be in the declared rules, not in any of the logic. And for that, they have hundreds of examples from me to copy from.

And if they do need to touch the "parser", at ~200LoC the complexity is certainly far below, say, a Spring J2EE code base. It's all in one file too, that shouldn't be too bad.

[1] If I may use HN as a small soapbox, actually, months later, I figured out a further small addition to that project that would've made working with it far easier. If any of my previous team recognizes this and this project is still in use, feel free to reach out to me for one last brilliant idea. :)

Sounds like a useful project.

> It's all in one file too, that shouldn't be too bad.

Fewer files is not necessarily better.

The guiding principle in my mind is reduction of entropy. If splitting one file into multiple files makes sense in the brains of the beholders it is a good thing.

200 lines in one file sounds fine on the face of it. I like it when I don't have to trace through to other files to see what's going on.
I haven't yet seen a DSL that wasn't a big improvement over compiling the DSL to a bunch of boilerplate in my head and making everyone try to reread the boilerplate forever.
Rocket materials don't ultimately compile down to the same material though. This makes the analogy somewhat flawed. Also, if a novel language feature is useful enough, it's often stolen by the competition.
From the article,

> [Lisp macros] by their nature would be hard to implement properly in a language without turning it into a dialect of Lisp

Other candidates that come to mind (because I recently learned about them) are effect systems, like in Koka.

Yes, I read that, but I don't know Lisp well enough to evaluate the claim.
I'd highly recommend learning lisp and writing some higher-order functions with macros. You start with an instance of a lower-order function, insert a few backticks and commas where appropriate, wrap that in a defmacro, and boom, you're a metaprogrammer. You can certainly do similar stuff in other languages, but it's almost always a cludge.

The rest of lisp is pretty easy if you've done any sort of functional programming, and view the code through a lens that translates (foo ...) to foo(...)

Mixin macros in D are just about as powerful, and D is not a dialect of lisp.

The main difference is: mixins are compile-time only, you can't add them to a running system like in Lisp.

In practice, it is a much smaller difference than it looks like.

I honestly haven't seen any evidence of this whole "think things you couldn't previously think" idea. The only interesting thing I've seen people be able to do by switching languages, is significantly improving static analysis, in order to save debugging cycles and improve production reliability. But everything else that is "interesting" is just different ways to generate code in order to reduce lines of code written manually, which is convenient, and is certainly fun for nerds like most of us here, but I really don't see it as this superpower that folks like pg seem to believe it to be.

A better analogy for new materials is new techniques, like machine learning and higher order abstractions over it, or new algorithms. But those are independent of languages.

It's a real thing, but I think (extrapolating from my own experience) it's much more profound and tangible if you're starting from something like C or pre-modern C++ and then moving to something more modern and FP-flavored. Modern popular language are on a much more even playing field versus 20 years ago. Even so, I still had one of these mind blowing "things I couldn't previously think" experiences when I finally ventured into Prolog and logic programming a few years ago. It's such an order of magnitude beyond my day to day C++ and Python nonsense, at least up until the evaluation model blows up exponentially.

I'd still like, as a learning exercise, to build some semi-practical small applications in Prolog, but I feel like I'd need an expert mentor to guide me.

I agree that there aren't a ton of convincing examples mentioned that aren't relevant to people who already agree w/the value of lisp-style macros -- but if you're interested I used the example of erlang when responding to a comment above: https://news.ycombinator.com/item?id=28343140

FWIW I do actually agree w/pg about macros; I use them day-to-day for more mundane things than his impressive fully-bottom-up approach to programming. But each time I do use them, I feel like "thank heavens I don't have to reach for some weird external codegen tool to do this".

See I don't really feel that way about macros. To me, codegen is codegen, useful for a bunch of stuff but not really anything special, and whether or not it is homoiconic doesn't seem like the fundamental question to me.

Don't get me wrong, I think homoiconicity and macros are really neat, I can get behind the aesthetic appreciation of different programming languages and syntaxes for doing different things. But people seem to want to convince me that there is some mystical mind expanding power to it, rather than just aesthetic nicety, and that's what I find unconvincing.

I think it's really about an interplay of mental models and domains. Hers's my one personal datapoint. I did my undergrad in math and discovered functional programming back then. Got real excited about it, read the Learn You a Haskell book and then sort of nothing happened. But I waited on that "mind expanding" stuff to pay off.

Then I got my first job, where they really only cared that I was good in python. Cranked out a bunch of python services, and got good at cloud stuff along the way. Decided FP and that kind of thing was "school stuff."

A few years later I found myself working at another shop doing backend Go/Kotlin. We were increasingly writing a lot of streaming stuff on Kafka, and could tell we weren't really "doing it right." Just gut feel that something was not as good as it could be. So we brought in a senior eng with a bunch of Kafka experience, who just sort of coincidentally had been working in Scala during that experience. We onboarded him onto Kotlin, but the code pretty quickly picked up a Scala style and flavor.

After about a year I couldn't shake the feeling of how perfectly this kind of functional thinking mapped to stream processing services. Especially when you're working on a framework like KStreams or Flink, being able to describe your transformations with these pure non-nullable functions was just perfect for the domain. When you squint a lot of the Option/Either monad stuff really helps you think about your programs as a linear flow of data, which is exactly what stream processing is.

When you look at a lot of the Java api's in the space of big data, they look functional. AFAIK thats not because a bunch of Java devs decided to use all the cutting edge Java functional features. Its because the stuff people were building in Scala just fit the domain so much better. So the Java ecosystem took those ideas and everyone is for the better.

At no point did I develop a superpower. Now I'm back to writing Python stuff in a new domain, and those insights aren't so valuable day to day. I try to make my code a bit more linear and functional, but can increasingly tell its not the practical choice. But if somebody needed me to write a high throughput reliable stream processing thing, I would immediately jump back to those patterns.

I agree with all of this and have seen many of the same dynamics in my career, but it just doesn't seem like this mystical mind altering eureka thing that a lot of people seem to make it out to be. To me it's more like, oh good, here are some more useful techniques that help get stuff done sometimes.
The other problem is the "productive-only" trap. You begin to hate art, essays and everything related with free time because you are not doing anything productive doing those.

This can expand to your tastes or everyday life by not wanting to learn X "just for the fun".

The amount of intellectual curiosity on a site called Hacker News always feels lower than it should be.
I'd say that (2) isn't a side point...

> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.

In my experience, there are tons of programmers who balk at anything more complicated than a for loop, to the point where they won't even read the surrounding documentation of a short block of code to try and understand what it does. That's the 99.5% of programming that pg is talking about. I'd guess that some 80% of programmers spend their entire lives in this regime. When algorithm/language researchers talk to software engineers about what programming is, sparks fly. Like the parable of the blind people examining an elephant, we're talking about the same thing, but our experiences with it are too different to reconcile.

If someone used Lisp, Elm, Rust, Elixir, Go, or even just JavaScript, they should know that these are SO vastly different in their mental models that "languages are solved" doesn't strike me as a reasonable argument at all.
(comment deleted)
Are they so vastly different? Other than perhaps Lisp and Elm, they are largely equivalent, with different levels of immutability on top of a largely imperative core.

At least mention prolog, forth, SQL or the like that are truly different.

They all have distiguishing features that can be emulated in other languages (to a degree) but will throw off even senior developers.

Lisp has its macros.

Elm has its type system.

Go, Elixir, and JS have rather idiosyncratic concurrency models.

Rust has its borrow checker.

Perl seems to be SO special that even proficient Perl devs aren't able to write performant code in it. /s

Sure, Prolog and SQL are much more different than the rest. But I didn't want to strawman here.

Rust’s ownership model (which is more than just the borrow checker, it’s the whole concept of one location actually owning data, and aliasing XOR mutability, and the pervading effects of this design on the language and its libraries) is a really big deal, even if it doesn’t look like it would be at a casual glance. It changes how you approach programming and reason about systems, and truly is (or should be used as) a fundamentally different approach to data flow and what’s possible, a smidgeon like Prolog in that way of being different, though not as much. I miss it very frequently when working in other languages (which is mostly JavaScript these days), because there are plenty of things that just become impossible to express reliably without it. Working in another language you can adopt conventions of writing in this style, but you can’t verify it without representing it in the type system, so the result will be riddled with holes in other languages.

(It is, however, difficult to disentangle some features that Rust’s ownership model requires but which aren’t necessarily a part of that ownership model: for example, algebraic data types are essential and expression orientation extremely desirable, but there are other languages which have those features without the rest of the ownership model.)

People often think memory safety without garbage collection is Rust’s shtick, but it’s actually the ownership model that’s Rust’s defining feature, underpinning everything and making that possible.

Correct me if I’m wrong, but Pony lang brings Rust’s ownership model to the max - so as a niche language, do check it out!
This is still a pretty narrow group. Throw in APL, Prolog and Z3.
I just started playing with Dyalog APL after listening to the Array Cast. It’s mind bending stuff even after being familiar with Numpy and R. Makes most languages look clunky and cluttered for array manipulation.

And the idea that a language can be designed around one data structure is elegant. Of course you get that in Lisp and Smalltalk as well. But having all those primitives that work over array structures is incredibly expressive.

I believe the array podcasters when they claim array languages can be several times more productive than other languages, at least for domains that fit well with arrays.

Not to mention that languages are not just a tool for communicating meaning: it's also a tool for communicating emotions and mannerism as well.
> but saying that languages don't matter, for us, would be like rocket engineers saying that materials don't matter.

This is a bad analogy. Programming languages all get compiled to the same machine codes. The human-readable version of that code doesn't actually matter very much, if at all, after compilation. Programming languages are tools for humans: they're either expressive enough or they're not.

A better analogy would be rocket engineers saying the CAD tool you choose to design your rocket in doesn't matter—and that has some merit.

My problem with these arguments from PG is that they require that you pretend (or ignore) all the real world evidence we have about what languages are actually useful to make things with. It’s all fine and well to talk about how great X and Y is, but meanwhile most people are actually making things in Java and Go.
But what real world evidence do we have? Mostly that languages "most people are actually making things in" are picked by the business on the basis of popularity, which is determined mostly by what people learn in university - which is determined mostly by what is currently most popular on the job market. It's a self-sustaining feedback loop that has little to do with relative utility of languages for real-world problems (at least discounting languages' library ecosystems).
This argument is self refuting. If inferior programming languages are being picked continuously by “the business”, we’d expect that businesses that pick “superior” programming languages to out compete the other businesses. We don’t see this, so one of the following is true:

1) Programming language quality is a non-factor in business success.

2) People like PG are wrong about what makes one language superior to another.

By the by, I have never seen a non-programmer executive demand a “bad” language be used for a startup. What I tend to see is grizzled ex-programmers ignoring the trends and picking the reliable and “boring” choice over the complaints of some IC’s. This is less a “clueless business” issue and more an acknowledgment of an unpopular truth: picking the boring language that lets the business focus on its core domain is better than picking something that excites the most vocal engineers.

The claim that learning weird languages will help you learn new ways of thinking about problems that may be helpful in other langauges, and the claim that using 'boring' languages is the correct default for building production systems, in no way contradict.
Do what you will with your own time, I’m no longer convinced that learning “weird” languages is an effective way to become a better programmer. From my experience as an IC and as a manager, learning how to write better is probably a better investment for professional growth, second to that would be better distributed system design.

If it pleases you, feel free to learn whatever. It’s why I know Rust and Haskell personally. But as career advice I am much more dubious, even though I once agreed with you.

I find that for a lot of problems reasoning about the core problem using a mental model akin to lisp makes it easier for me to come to a sufficiently clear understanding to be able to better express the solution in both code and prose.

So while I agree about writing prose, it's also true that learning lisp made me a better documenter.

Having worked professionally in lisp, I have no idea why people say this.
Programming is full of things where what works for one person isn't at all what works for another.
Which is why I said “I have no idea” rather than “it doesn’t work that way”.
> If inferior programming languages are being picked continuously by “the business”, we’d expect that businesses that pick “superior” programming languages to out compete the other businesses.

That assumes that the software business is efficient in the market sense, which my experience suggests is very much not true. On the contrary, I've found that success hinges primarily on the ability to find and execute good business deals (which is the work of executive team and/or sales&marketing). Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.

> I have never seen a non-programmer executive demand a “bad” language be used for a startup.

I've worked for one many years ago. I was actually promised the free reign over technology stack for a project, until the CEO decided to override me and order me to use a very particular and shitty combination of technologies. He was very up-front with me about his reasoning: he said, "yeah, I could let you write this in something more reasonable, say Ruby or Python, but programmers for those languages are expensive, PHP programmers are much cheaper, and I'm going to be hiring more people to help you".

(I run the project solo for the next year, because he eventually decided not to hire anyone.)

> picking the boring language that lets the business focus on its core domain is better than picking something that excites the most vocal engineers.

Be careful not to mix up topics here. What usually "excites the most vocal engineers" these days is the things they can use to pad their CVs. This usually goes against what the management wants, which is whatever stack they've read about on HBR or whatever one is cheapest to hire people for. Neither of those tend to have anything to do with powerful and advanced tooling.

> That assumes that the software business is efficient in the market sense, which my experience suggests is very much not true. On the contrary, I've found that success hinges primarily on the ability to find and execute good business deals (which is the work of executive team and/or sales&marketing). Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.

I actually covered this in literally the next line.

ashtonkem: To quote what you wrote two sentences afterwards:

> 1) Programming language quality is a non-factor in business success.

What TeMPOral wrote (below) is is not quite the same in my view. First, they elaborate more. Second, there is a different argument:

> Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.

Namely: it is NOT the case that software does not have a business effect. Rather, other aspects of the business have to work extra hard to compensate.

To take a systems point of view: two systems can have the same output over some time period but very different internal efficiencies.

> yeah, I could let you write this in something more reasonable, say Ruby or Python, but programmers for those languages are expensive, PHP programmers are much cheaper, and I'm going to be hiring more people to help you

It sounds like the exec made the right choice. PHP is a wildly successful language that powers an obscene portion of the Internet web apps.

That’s not a “bad” language, it’s just an annoying one for engineers to work with. A bad language would be one with so little adoption and such a steep learning curve that hiring new software engineers is a year-long path to expanded productivity.

The further you dig into the matter, the more you realize that most people’s definitions of “good” and “bad” languages map onto their own personal preferences, not anything concrete about the language or how it’s used.
This is bullshit because popular languages have changed and emerged from outside of university (see Go, Python, etc that had no university presence and exploded in popularity in industry).
You don't have to use a language to benefit from its existence. Haskell is a weird language that nobody* uses in production, but it's where a lot of functional programming concepts were refined and ultimately made their way into mainstream languages. I use functional programming tools in Java and JS very often and they only exist because many people tried Haskell, saw the potential of this new* paradigm and implemented parts of it into their environments.

Similarly, having been forced to learn Prolog in university, I now have a completely different view of solving problems. And while I'll surely never touch Prolog again, this new perspective allows me to write much better code in some cases, despite working in a completely different language.

I second this. It's always about learning the mindset even if you don't use it for real life. Same for learning mathematics, music, philosophy, etc. It becomes your mental model to apply to other aspects of life.
I used to argue this. Then I watched multiple engineers under me and next to me ignore this argument in favor of focusing on distributed system design and clear communication. The results have persuaded me that I was wrong, and they were right.

In the end the most effective people around me are capable of designing a system and breaking it down effectively for other engineers to build. Most of them have no idea what things like Monads and Functors are, and they’re no less effective for it.

PG's arguments are not forcing you to pretend (or ignore) anything.

I think it's possible you are falling prey to the either/or fallacy.

> What can you say in this language that would be impossibly inconvenient to say in others?

This ideology is why I believe so strongly in the power of SQL (and similarly-expressive functional/DSLs). They are effectively limitless in their ability to describe problem spaces. In SQL, joining 30 different dimensions of data is a matter of the same # of lines of SQL. Doing such a thing in any imperative language would be a medium nightmare at best. Even with LINQ at your disposal, this is not fun.

I actually did not realize it was possible to construct a useful piece of business software that exclusively uses SQL for its domain logic until ~18 months ago. Turns out the trick is to go all-in and just make sure 100% of the relevant domain state is represented in the schema. You also have to understand why database normalization is important if you go down this road. The only reason you would fail to model something properly is lack of imagination, experience and/or discipline. These tools are limitless.

There is also the benefit to the business. You can print off all of the tables as excel spreadsheets and review them with non-technical stakeholders. I find this much preferable to explaining how procedural code works to non-wizards.

So, I would say - Weird languages - Absolutely yes.

But, also go check out some of these new tricks you can teach to old mainstream things. If you want to play around with these ideas, getting SQL into your application is absolutely trivial with SQLite these days. We are using it in production for this purpose right now. My project managers are more familiar with the product's schema than I am at this point, because they are authoring BL in SQL today. This is where you really want to be, IMO.

“You can print off all of the tables as excel spreadsheets and review them with non-technical stakeholders.” Try something like Metabase. Just place the SQL in there and you get a URL that gives you dynamically updated “Excel”.

I like this way of business development: Prototype some SQL, place it in Metabase, get feedback, update the SQL, when they are happy, make it to an Update that solve their need automatically.

And it gets way more powerful when you learn Macros in PL/SQL or PostgreSQL so that you can dynamically change the SQL based on results. One example is to build the Metabase functionality into the business application do that you can easily add/change SQL, and the resulting values automatically is clickable if the data comes from the right tables/views.

The thing I've always had trouble with from there is extending and versioning domain logic, both for new features as well as for rollback. What's worked for you here?
I use a lot of views for abstraction and backward compatibility.

Rollback is always difficult on live systems, especially when the data propagate to integrations. I try to always have 'first created' and 'last changed' time stamp, and first created and last changed user. If the job is automatic the “user” should be traceable back to the individual job, not some generic system user.

I had great success maintaining views (and tests on top of them) for the business people by using dbt. Everything is in git and gets deployed along side our fivetran sync.
I feel like with SQL although, you could reproduce the vast majority of usage of it with about 5 very large functions / objects, which is what it essentially is in most usage.
I feel like LINQ is pretty close to the equivalent SQL if you're already using DataTables or some other easily composeable type. But I agree SQL is great.
Funny you should bring up SQL. The "learning how to think things you couldn't previously think" resonated with me also, specifically when I realized that SQL would be so much better if joins were values instead of language constructs. I can't imagine I would have come up with this thought if I hadn't been working in Racket with the substitution model (as taught by SICP) fresh in mind.

Sections 5.1.1 and 5.1.2 in my side project demonstrate what I mean by "joins are values": https://docs.racket-lang.org/plisqin/Refactoring_Recipes.htm...

There was this analogy about programming language proponents.

Language A has features 1, 2, and 3. Language B has features 1, 2, and 4.

Language A user thinks they're superior because they have feature 3, which B lacks. B's feature 4 they don't understand, but they've never needed it so it's useless.

Language B user thinks the opposite, of course.

(this was much better explained in an article that graced HN a while back, and I can't find anymore)

Looking at functional languages helped me understand the point of all a little better, to the point where I write completely different imperative code now. I'm much better at reducing state, leveraging static calls / libs etc..

But I'll probably never use a functional language in production.

The Rust borrowchecker is an awesome idea, I don't quite like Rust and don't want to use it, but I'm excited for the concept to be introduced into established or newer languages - and it helped me reason about my own programs a little bit.

Even beyond personal curiosity, that was time well spent.

> saying that languages don't matter, for us, would be like rocket engineers saying that materials don't matter.

It also seems plainly mistaken. We still see a steady stream of security vulnerabilities relating to imperfect use of unsafe languages. Safer languages make those sorts of errors categorically impossible. Even if your position is sure but these languages aren't always practical, that's still a concession that further work is needed on safe languages.

In my experience, as you learn more about lambda calculus and type theory (LC, STLC, System-F, System-Fw, CiC) the peculiarities of language designs start to fade. This is because when you see a weird-looking language feature, instead of internalizing it as a unique design with its own unique character, you tend to see it as "syntactic sugar" on elemental theories.

That said, some languages are more ergonomic than others, especially when you compare them against particular domains. But IMO that's a problem that transcends language design. All tools, not just a language, should be fit to the domain. And in general you can build APIs and libraries that can reasonably fit any language to a domain.

Edit: slight simplification.

I'd definitely agree with the specific point of both paragraphs, especially because you said 'language designs' in the first. But I think the essay uses 'language' to mean what you do in your second paragraph, 'features'/stdlib/ecosystem -- the whole experience of working with that material in practice.

And in that sense, I think the value of 'weird' languages is that they can package so many different mutually-reenforcing design decisions together that they literally can have the 'think different' effect described in the essay.

Taking one example that's kinda-weird, kinda-mainstream -- a 'language' like Erlang includes way more than a Prolog-inspired syntax for a simple functional language, and when you look closely at it, it's not simple to just recreate by pulling in features ad-hoc; the language, its stdlib, and its VM complement each other and have informed each others' design.

Probably the feature that most comes to mind when we think of Erlang is that it 'goes all-in' on message passing in a functional language. 'All in' meaning that they've made decisions like: being willing to copy a lot if needed, little details like keeping a count of reductions, big things like pulling in concerns that are often left to the OS when working in other languages like process scheduling, preemption, and supervision, and providing a toolkit out of the box that supports building full systems via Nodes with Applications with trees of Supervisors of Processes (all of which are effectively language concepts now), etc. Well, every one of those decisions is eyebrow-raising to somebody or a lot of somebodies. But if you do go all-in on that combo of capabilities, what's it like?

A good engineering team with a lot of money can fit another language and another VM to the same kinds of domains that Erlang is a fit for. (Not that you can get people to agree what those domains are, even within Ericcson apparently). But their solution will necessarily look very different, and the difference between what's easy/hard in their approach vs. an erlang-ish approach is what the weird language can teach us.

The whole explanation of your point is just filled with analogies. IMO if you have to use analogies to explain your point then you really don't understand your own point.

When programming, I am thinking in terms of data, what processing the data needs, how will you structure the data in memory/disk, what IO/integration is required etc. This thinking has nothing to do with what the programming language allows/makes you to think. If your programming language is supposed to dominate your thinking about programs then you are just constraining yourself to a specific way of solving the problem.

This rocket analogy falls flat because the languages that have been used to build the most scalable and/or complex systems of today are usually the boring ones (c/c++/Java/python/ruby/JavaScript).

Linux, llvm, Android, iOS, git, cPython, numpy, etc, etc. From operating systems, to compilers, to scientific computing, to literal rocket control systems, it’s mostly boring C/C++/obj-C/Java.

Is that true? WhatsApp, Discord, and Facebook Messenger are Erlang. Some pretty extreme scale systems, I'd say.
Some of these companies are so insanely huge that they have dozens of technology stacks, so I would not attribute elixir specifically, to the latter two at least (wasn’t discord rewritten in rust not too long ago?)

And facebook itself is historically PHP (where they had to fork the runtime even), but they use plenty of other boring tech (eg. Java), as well as some exotic ones, notably haskell for some query pre-optimization (afaik)

They rewrote some services from Go to Rust, but have always been a huge elixir shop. They wrote some NIFs in Rust too.
Ah, this reminds me of the days I spent writing RPL programs for solving electric circuits on my trusty old HP48 calculator. (It is said but nowhere officially confirmed that RPL stands for "reverse-polish lisp".) It was quite enjoyable _then_ and for _that_ purpose (programs designed to run in a specific UI environment) but today I wouldn't even consider starting a "serious" project in a postfix language. EDIT: https://factorcode.org/ is a modern postfix language.

Using weird languages DOES have one merit though: it opens your horizons. It teaches you to see a "conventional" programming language as a collection of mechanisms at your disposal instead of something "intended to be used to do X".

More to the point, I think that there are two types of languages: 1) those that encourage top-down design (that's how I learned programming with Pascal) and 2) those that encourage bottom-up design (such as RPL, these have often an interactive REPL.)

So actively using something like RPL or ML or Scheme (yeah, I've read ca 2/3 rds of SICP) allows you to turn C# "inside out", to apply bottom-up programming techniques. You don't create a class because "some OO principles tell you to do so" or because it came as godsend from some "architect", but because you understand workings of classes and a class is the right tool for the task at hand.

Also, there's no programming in the large without some mechanisms to control accessibility.