> There's no native Unix equivalent to frequencies, this sort | uniq -c is the closest we can get. Not only is it less performant (it has to collect the full input into memory before continuing), but it ties aggregation to ordering.
One of the core features of the Unix command-line is that it is user-extensible. If there's no "native" command equivalent to frequencies, you can write your own, and it will be given the same first-class treatment as any other binary in your PATH. This is entirely in keeping with the Unix philosophy of simple implementations.
Yeah, that point was weak. The argument went from "Unix pipelines are not simple" to "unix based operating systems don't have an equivalent to Clojure's frequency function by default so it's worse"
OK but how would it look like if you had such a program? Shells are not known for having the extensive set of functions that real programming languages have.
I think the article is a bit weak when it's making this point, because it's not about Unix pipelines. It's about POSIX shell utilities being too bare-bones.
But Unix pipelines are not simple too. They have a couple of nitty-gritty details that often come out and bite you.
1. They can only stream raw bytes, so all the programs that deal with lists like sort and uniq have to separate items using a delimiter (usually newline). If you want to process data with that delimiter in it, you're in for a ride. And if you want to write a custom tool, you have to do all the splitting yourselves (luckily it's so common most programming language will provide a ready-made facility for you to do that). This is New Jersey approach again: "I'll make my code (the OS, the shell) easier to write, and in return make life harder for my users (the tool writers)".
2. Error are hidden by default in shell. Nowadays you can explicitly change this behavior, but you have to remember to do `set -o pipefail` and I don't think it was always there.
3. There is no data typing at all. Everything is binary or text. Nowadays a lot of programs just output JSON, and the users (if they even stay inside the shell) almost always reach for jq to parse it. But jq is not a Unix philosophy program: it's an entire streaming functional programing that can do quite a lot. But even jq gets hairy when you have to do a bigger query or transformation. In that case users often reach out to Python or another language and just move the business logic there.
I think this fits well with what the article is trying to say: Unix pipes are pretty easy (small) to implement on your own (compare that to something like Nushell's pipes). But the moment you to do something that's a little different than the happy path it was built for, you need to go for another tool (jq) that has its own built-in pipe and small programming language, because Unix pipes won't cut it. And for more complex (hehe) things, you'll have to reach for a larger (and simpler) tool: a full-fledged programming language.
> This is New Jersey approach again: "I'll make my code (the OS, the shell) easier to write, and in return make life harder for my users (the tool writers)".
I'm not sure if you're actually trying to argue for a specific position here, but you highlight several negative results of one "philosophy" of development, with the implication that the alternative wouldn't have those negatives.
This is a tricky point to refute because you're right, these are flaws and there could be a system that doesn't have them.
So why do these flawed systems exist and proliferate?
Because the real life result isn't actually a choice between "sloppy but quick to develop" and "elegant well engineered but slow".
The choice is actually between "sloppy but exists" and, well, nothing, because the other version never actually materializes.
(And of course, I feel compelled to point out that bash is a user interface not a programming language. Any attempt to replace it or improve it without focusing on that main point is doomed to failure, which is why you see so many people who apparently think that what bash really needs is strict type checking or something and end up creating a completely awful user experience)
I think the point was more that it's hard to compose shell utilities to make something new that's not supported out of the box. Instead you do have to write an entirely new utility and use that.
That said having key/value semantics and not just stream of bytes would make the shell much more versatile, at the cost of making it bigger.
That's not what the linked article is saying. The point made in the article is that the 'uniq' utility couples together two unrelated concepts--sorting and frequency counting--and this coupling forces you to write more complex code, compared to the version where frequency counting is decoupled from sorting.
All of this is completely correct, but it has nothing to do with bash vs. Clojure. The same decoupling can easily be achieved in either language.
This was my thought, too. Either you can extend your toolkit—make a utility like dedup (https://codeberg.org/napcakes/dedup) and put in on your path (yay! so easy)—or you can't and thus must define the boundary of the allowed toolkit. In this case, it seems overly disingenuous to not allow awk, which will do the thing for you just fine, no Clojure needed at all. awk is hashmaps galore.
Honestly, so much of our conceptions of "what's wrong" is more to do with lack of familiarity with history than any actually unsolved problem.
The oldest defer-like feature I can find reference to is the ON_BLOCK_EXIT macro from this article in the December 2000 issue of the C/C++ Users Journal:
I thought the "free" in "free web" was supposed to mean "free as in freedom," not "free as in beer." Have we really reached the point where the CEO of Mozilla no longer understands or cares about that distinction?
There's plenty of application-level C and C++ code out there that isn't performance-critical, and would benefit from the safety a garbage collector provides.
Right, does `sudo` net benefit from removal of heap corruption, out of bounds, or use after free, etc errors that GC + a few other "safeties" might provide? I think so!
>3) Comma-separated list that's exactly 3 items long
Proper typography and hamburger paragraphs are canceled now because of AI? So much for what I learned high school english class.
>2) "It's not X, it's Y" sentence structure
This is a pretty weak point because it's n=1 (you can check OP's comment history and it's not repeated there), and that phrase is far more common in regular prose than some of the more egregious ones (eg. "delve").
It's possible that without the medication, you wouldn't have gotten burned out like this. But it's also possible that you'd have missed out on all of the benefits of being medicated and still gotten burned out anyway.
import std.meta: AliasSeq;
enum E { a, b, c }
void handle(E e)
{
// Need label to break out of 'static foreach'
Lswitch: final switch (e)
{
static foreach (ab; AliasSeq!(E.a, E.b))
{
case ab:
handleAB();
// No comptime switch in D
static if (ab == E.a)
handleA();
else static if (ab == E.b)
handleB();
else
static assert(false, "unreachable");
break Lswitch;
}
case E.c:
handleC();
break;
}
}
Thanks! That indeed does the equivalent as the Zig code... but feels a bit pointless to do that in D, I think?
Could've done this and be as safe, but perhaps it loses the point of the article:
enum U { A, B, C }
void handle(U e)
{
with (U)
final switch (e) {
case A, B:
handleAB();
if (e == A) handleA(); else handleB();
break;
case C:
handleC();
break;
}
}
The only thing I find bad about Google search now is their "AI" summary, which is often just wrong. I can deal with ads in the search results, I expect them, and I have no doubt ads will be shown in ChatGPT search results too, because they are bleeding money. And ChatGPT is under no obligation to show you anything with any accuracy, which is what the underlying tech is based on - guessing. Thanks, I'll take my chances with actual search results.
I think AI evangelists avoid talking about search because AI is why every internet search engine sucks. I use DuckDuckGo and Startpage, and when trying to find answers to nontrivial questions I get ONLY AI spam sites as results. (Come up with 1500 semi-specific SEO-friendly articles vaguely relating to subject the theme of website N. Then repeat until N=100
And shortly enough, AI is not even going to help with searching – it will eat its own s*t and offer that as answers. Unless the AI giants find some >99.99% way to filter out their own toxic waste from the training data.
There was a period I remember fondly when the SEO slop was still mostly human generated because AI couldn't quite do it yet, and I was getting much better results from DDG than from Google. Now it's all despair-inducing.
What you're saying is totally correct about AI slop polluting the web, but the reason they don't want to talk about it is because the second they frame "AI" as slightly better search, it invites all sorts of unfavorable financial comparisons. It also deflates the hype because now you're talking about a better version of a thing everyone is familiar with instead of some magical new buzzword like "agent" or "RAG" or whatever we're going to be talking about next year when agents don't work.
That's possible, but then the people building your extension need a C++ toolchain.
The question was "please provide examples where switching to C++ involves jumping through even more hoops", and in my view requiring downstream to use a C++ environment when they're expecting to use a C environment qualifies.
Problems in this domain arise more because you’re wandering off the beaten path for configuration and tooling than because the systems lack absolute capabilities. If you don’t want to build your extension the way that the extension framework expects you, all sorts of annoyances show up. Maintaining an cross-platform compatible C extension is hard enough already.
One of the core features of the Unix command-line is that it is user-extensible. If there's no "native" command equivalent to frequencies, you can write your own, and it will be given the same first-class treatment as any other binary in your PATH. This is entirely in keeping with the Unix philosophy of simple implementations.