Hacker News new | ask | show | jobs
by bsder 15 days ago
> Programming language syntax scarcely matters.

Certainly it matters much less in the modern era.

However, certain fundamental decisions of a language can be dealbreakers.

Requiring declarations on your functions and giving those declarations sigils so that they can be parsed quickly is an important syntax decision. Almost every modern programming language has converged to this idea.

Or take, for example, Lua. For me, personally, the 1-based-ness of Lua is simply a dealbreaker no matter how good anything else about it is.

For the "Lisps", I LOATHE the fact that you traverse lists and vectors in completely different ways--you can't just drop any container-ish thing into something that iterates/collects it. This is something that both Clojure and Racket seem to agree on--you have something that acts like a "collection" and you can walk across it the same way regardless of the specific type of collection it is. Of course, that is why a bunch of Lisp purists loathe Clojure and Racket while I like those languages. Shrug.

I find RAII (Resource acquisition is initialization) to be the source of all things evil if it infests a programming language. The popularity of C++ and Rust speaks to the quite large number of people who think my opinion is bullshit.

So, yeah, base syntax matters far less than it used to. But the engineering decisions that went into making that syntax correspondingly are far more important.

3 comments

I agree with most of what you said, but I am puzzled about your claim about RAII.

Whether it is good for any kind of resource acquisition to look the same like an initialization is debatable.

On the other hand, I cannot see any counterargument to the principle that releasing any resources should not be done explicitly, but only implicitly, upon leaving a block (using reference counts for shared resources).

I doubt that you advocate for the use of explicit release commands for resources, which are a notorious source of bugs, so what is that you consider as not being the same as RAII?

RAII was a not very useful acronym that was just another form to say that the C or C++ programmers should never use the PL/I style of explicit free commands, despite the availability of functions like "free()" or "close()" in the standard library, but both memory and files and any other kinds of resources should be managed with automatic releasing.

I do not see how this sound principle can infest any language.

Obviously, I have seen examples of bad RAII implementations, like I have seen examples of misuse for any other programming principle.

> I doubt that you advocate for the use of explicit release commands for resources, which are a notorious source of bugs, so what is that you consider as not being the same as RAII?

Those are not the only choices.

Garbage collection is at one end of the spectrum--fully manually managed is at the other end of the spectrum. There is also another axis of acquiring/releasing allocation by object or acquiring/releasing object by pool. And, if you have it, there is the axis of allocate only at startup and never free until end of thread/application vs. allocate only at a frame of of time and then destroy them all at the next frame vs. allocate whenever and wherever.

RAII encourages the usage of lots of tiny individual objects allocated whenever and wherever all with their own lifetime cycles and makes understanding the memory usage of your application very difficult (this was the whole reason Rust was made--C and C++ made managing memory in Firefox ridiculously diffused and impossible to corral).

And, I'll be blunt, I think that Rust/Zig/C3 etc. are not the right direction in spite of the fact that I use Zig a lot. I think that the garbage collected languages cede far too much in terms of performance to the compiled ones and GC languages (like say OCaml) should be being used for systems programming more often.

For example, I think we would all be in much better shape against AI vulnerability scanners if more systems programs were in GC-type languages.

> I LOATHE the fact that you traverse lists and vectors in completely different ways

In Racket:

    (for ([x xs]) (displayln x))
This works for `xs` being a sequence, which includes lists and vectors.

Making the type explicit generates faster code:

    (for ([x (in-list   xs)]) (displayln x))
    (for ([x (in-vector xs)]) (displayln x))
Yes, this is the kind of thing why I like Racket and Clojure and so much of the Lisperati don't.
I think we can easily agree they are two entities (syntax / runtime) that feed off of each other. And I do agree that previously the syntax mattered more.

(I very much agree on Lua btw.)

Personally I am very disheartened. Surely algebraic data types should be universally a good thing and all PLs should gradually adopt them? But no, endless HN / Reddit threads bike-shedding.

Oh well.