News for hackers. Stuff that matters.

OskarS

Re:Nixpkgs for the Front End Impaired on Thursday October 29, 2026 @10:30AM (#50289720)
Yes, you're absolutely right, but you're also illustrating the author's broader point a little bit. For someone not very deeply familiar with Nix (the language), that is a very difficult one-liner to parse. You have to be pretty hard-core nix-pilled to understand what that one is doing just reading it straight-on (my NAS is using NixOS, so I've written some amount of Nix). On the other hand, the TypeScript code the author provides is reasonably straight-forward, you don't have to be particularly familiar with either TypeScript or Nix to understand what it is doing.

You're correct in that the article is wrong in saying you can't use a nix repl this way, but I took the broader point of it to be "Nix-the-language gets in the way of the Nix-the-model". Which is something that I personally agree with 100% and I think the article illustrates beautifully.

It's a very lawyerly distinction you're making here that's willfully blind to what's really going on. The common-sense reading "primary, common, local name" is that it should be called the Gulf of Mexico, as that is what it is called in the USA.

If the nutso president of Turkmenistan decided one day that the Caspian Sea's real name was the Turkmen Sea, there's absolutely no way that Google Maps would rename it on their maps. The reason they renamed it in this case is not because "well, the government said so, so we have no choice!". It's (obviously!) done to not piss of Trump, and pissing off Trump would be bad for their business. They can hide behind lawyerly arguing all they want, but that is the real reason.

Re:Composite objects and C++26 the std:polymorphic type on Wednesday October 21, 2026 @05:07AM (#50177909)
I agree. The comment is correct in that it sort-of violates the "purity" of std::indirect that it has this pathological in moved-from state, but it's only an issue when directly using moved-from objects, which is something you essentially never do. Exactly what you say, "in practice" this never happens. Throwing the move constructor out because of it would be throwing out the baby with the bathwater.

std::variant has a similar issue with valueless_after_exception, which given the semantics of the language, it has to have. But similarly, this essentially never happens in practice, and I've never encountered a bug with a valueless std::variant.

Re:Composite objects and C++26 the std:polymorphic type on Wednesday October 21, 2026 @04:42AM (#50177728)
> Which the version I showed has none of.

No, it has something much worse, it has a memory leak. The nested types inside the union allocate memory, and they don't get destructed when Event gets destructed. Don't do this in modern C++, it's a terrible terrible idea, these kinds of constructs are very hard to get correct manually. Just use std::variant.

Re:Composite objects and C++26 the std:polymorphic type on Wednesday October 21, 2026 @04:36AM (#50177684)
Yes, though in modern C++, don't do this, use std::variant instead. It has better type-safety (nothing stops you from writing to one member of the union but reading from another, causing UB) and handles lifetimes much better. Your version leaks, because struct Event wont destruct any of the nested types inside the union, and in the example, they have heap-allocated data (std::strings and the like). In order to that properly with a tagged union, you need to define the destructor of Event yourself (which is not done in your example) and call the correct destructor manually of the active union member.

Tagged unions (especially with resource-managing types) is hard to implement correctly in C++ (and not trivial in C either). Don't do it, use std::variant.

Re:Writing Efficient C++ Code on Monday September 28, 2026 @10:51AM (#49878947)
> One in a trillion times.

This is wildly overstating it. Yeah, I agree, they're much less often the right choice compared to a good-ol' growable array, but they have lots of uses in high-performance code and concurrent code, and they're building blocks in lots of other data structures. Like, in a bucket hash-table, the buckets are linked lists, in a LRU cache you interleave a hash table and linked list, std::hive is a linked list of chunks of elements, etc. Anything that has ever had to deal with memory pooling/allocation uses free-lists which are linked lists. And on and on and on.

Re:A Necessary History of the Oddest Letter: W on Monday September 21, 2026 @10:20AM (#49787656)
I remember vividly being so annoyed when they added W to the Swedish alphabet in 2006. The alphabet I learned to recite in first grade is suddenly wrong?! I still don't say it correctly unless I concentrate, if I have to recite the alphabet, I always skip over W.

The argument at the time was that no "native" Swedish words are spelled with a W, so it shouldn't be part of our alphabet. However, but 2006, enough loan-words had been imported to Swedish with W's (like "webben", "the web") and it was in enough brand names (like "Volkswagen") that it should be included.

But I'm still mad about it! This is my tiny ridiculous hill to die on, W should not be part of the Swedish alphabet!

Re:High-performance garbage collection for C++ on Tuesday September 15, 2026 @06:30AM (#49710314)
It's interesting reading this, wondering how much C++26 static reflection could improve the ergonomics of a system like this. Like, if you tag the class with a specific attribute, can you have have it generate the Trace() function automatically? Can you have it automatically wrap the other GC classes using the Member<> template? I think implementing the Trace() function might be doable (you'd do it in the GarbageCollected<> base class that uses CRTP, right?), but maybe not wrapping the types, I'm not sure if reflection allows you to modify types of fields in that way.
Re:Move in C++ without a std:move on Thursday September 03, 2026 @04:35AM (#49547443)
Fair enough, I don't know the C++ ABI to this extent.
Re:Using jq to format JSON on the clipboard on Wednesday September 02, 2026 @10:25AM (#49536758)
Lovely little alias, but I much prefer fracjson[0] pretty printing to jq, so I might go with that instead!

[0]: https://github.com/j-brooke/FracturedJson

Re:Move in C++ without a std:move on Wednesday September 02, 2026 @09:52AM (#49536244)
Yes, it works exactly like this, this is a demo on godbolt [0]. rdi stores the pointer in both cases, makeS1() uses RVO, makeS2() takes it explicitly and constructs with placement new.

I will say before testing this i didn't realize the RVO calling convention was to return the pointer you pass in, but apparently so. If makeS2() returned void, it's just a tail call to the constructor, but makeS1() has to spill rbx and use it to save the pointer.

[0]: https://godbolt.org/z/ovd1n99P8

That's what I'm saying, if you have a CoW filesystem, backing up with atomic snapshots is almost certainly fine, SQLite's advice against copying probably doesn't apply to that. But just typing `cp` in a terminal is probably not a good idea if a transaction is active (even if you're on a CoW filesystem, `cp` in experience usually isn't atomic without some flags).
> The simple way to fork a sqlite db is just to copy it

SQLite recommends against doing that [1] while a transaction is active, because the copy might have some pre/post data in it which could potentially cause corruption. Presumably this isn't an issue with copy-on-write filesystems assuming they copy atomically, but I probably still wouldn't do it, instead use the backup API or VACUUM INTO (if nothing else, because VACUUM INTO will also obviously VACUUM the copy).

If you're not attached/writing to it, then of course it's fine.

[1]: https://www.sqlite.org/howtocorrupt.html#_backup_or_restore_...

Re:uv: Deduplicate all files in the wheel cache on Monday August 31, 2026 @07:25AM (#49508371)
I think it's reasonable for a DB like SQLite to delegate that to the filesystem. There is an overhead for doing it on the DB level, and since SQLite is just a file on the filesystem which, presumably, is serving many other files as well, why would you trust anything else on the filesystem if you don't trust SQLite? Like, your PHP script (or nginx server executable, or whatever) that is calling SQLite, that's not going to be check-summed either. Either you trust your filesystem or you don't, and if you don't, checksum and error correct on the filesystem level.

Though fair enough, it could offer it as an opt-in thing.

Re:Nebula Sans on Thursday August 27, 2026 @05:34AM (#49462052)
I think that's totally fair, it's just different people come to youtube for different things. Nebula is just a different value proposition.
Re:Nebula Sans on Wednesday August 26, 2026 @12:30PM (#49451866)
Obviously YMMV, but I haven't had any issues like that, the quality of the videos is the same I get in the YouTube app. They take a few seconds longer to start though.
Re:Nebula Sans on Wednesday August 26, 2026 @12:27PM (#49451802)
Yes, of course you can, but this sense of always having to curate your watch history and hide from the algorithm is just not there for Nebula. I guess it's different from person to person, but it's remarkable how freeing it feels to me to use a service where that isn't a concern. I'm watching what I want to watch, not what the algorithm is manipulating me to click on.

Maybe it will enshittify like most everything else, but it hasn't so far, and for now I'm a very happy customer.

Re:Nebula Sans on Wednesday August 26, 2026 @11:43AM (#49451112)
It's a little beside the point of the post, but I just want to fly a flag for Nebula: I subscribed solely to get early versions of Jet Lag: The Game, but I'm finding myself watching it more and more! It has many of the channels I would go to YouTube for, but I've also discovered several really good ones that I had never heard of. And it has a similar feel to Kagi, in the sense of "freeing" yourself from the algorithm. It happens so often on YouTube that I see a video recommended but think to myself "if I click this, am I going to get recommendations for terrible stuff for the next month? What does this tell Google about me?". Same thing with all the big streaming services.

With Nebula, no such worry. The homepage and app isn't creepily algorithmically designed to optimize my engagement with the platform, it's just a bunch of high-quality videos and channels that I can watch with no fuss. It's remarkable how nice that feels in 2026. Really highly recommended.

Re:GIMP Development Update on Monday August 17, 2026 @04:48AM (#49327999)
The obvious alternative is SQLite, and it has many advantages. If you want to do a "zipped list of files", SQLite does that just fine (that's what SQLar is), but it can do so much richer data. Even if you don't want that, it still offers resiliency that "zipped XML" can't match: if your software or computer crashes in the middle of saving your file, it'll almost certainly corrupt it. With SQLite, not an issue: all transactions are atomic, they either happen entirely or not at all.

I don't know what "mature tooling" you're talking about for zipped XML, but I guarantee you it's not going to be better (or more mature) than SQLite and its ecosystem.

mem::forget isn’t the only way you can safely leak a value, you can do it with reference cycles too, right? And there is no way for the compiler to detect that?

Isn’t that why mem::forget is safe, because you can always implement it yourself safely? How do you get around that?

Re:Stinkpot: SQLite-Backed Shell History on Sunday July 26, 2026 @04:52AM (#49056064)
I think you're underestimating the speed of modern computers and hard-drives, fzf can search through 100k entries easily without any delay. Try it with `cat /usr/share/dict/words | fzf`, it's extremely responsive (my dictionary is about 235k lines). If you want hard numbers, try piping your shell history through `time grep` and see how long finding an entry takes.

Even if you're on spinning rust, your shell history is probably in cache. You don't really need FST index for this usecase, IMHO.

Re:Prefer Strict Tables in SQLite on Sunday July 12, 2026 @07:18AM (#48880208)
Does this trick work with foreign keys? Like, if you have an ON CASCADE DELETE, does it delete a bunch of rows in other tables when converting the table to strict?
One useful thing to do sometimes when looking at whether or not a user is interested in participating in Wikipedia or just participating in arguing about things is to look at their contributions to actual wikipedia articles, the thing Wikipedia is all about.

This is the list of articles Sanger contributed to in 2026: [1]

Compare that too all his contributions: [2]

Does it seem like this person is participating in Wikipedia in a genuine way? Or is he there to start political arguments on various internal pages?

[1]: https://en.wikipedia.org/w/index.php?title=Special%3AContrib...

[2]: https://en.wikipedia.org/w/index.php?title=Special%3AContrib...

Re:Correlated randomness in Slay the Spire 2 on Tuesday June 16, 2026 @12:54PM (#48558227)
They can certainly be part of the standard library, it's just that you have to make the programmer be specific: it's a bad idea `new Random(seed)`, because you can then never update the `Random` class, and you might get stuck with a terrible default forever. But having a `new Xoshiro256(seed)` is a fine thing to have in your standard lib, given that quality PRNGs are such a common need.
Re:Correlated randomness in Slay the Spire 2 on Tuesday June 16, 2026 @08:30AM (#48554196)
I've always thought that random number generators are one of the best examples of Hyrum's law ("all observable behaviours are part of your API"): once you release a random number generators that either uses a default seed or allows you to seed it, you can't ever change it, it's a huge breach of backwards compatibility. Imagine if you did a Minecraft style game that relied on the behaviour of some PRNG, and then you changed the implementation? The entire game will break. That's why GNU libc still uses a terrible LCG for rand() despite the fact that much better generators exist: they can't ever fix it, because srand() exists and people rely on it.

On the other hand, it's STUPENDOUSLY useful to have "default" random functionality in your core library, for the "just give me a random number" or "shuffle this array, I don't care how" users, who don't really care about the details. But if you do that: always seed it with some external entropy (current time or /dev/random or whatever), don't even allow users to seed it. That means you can improve it in the future, because users already can't ever rely on the sequence. If the users do want to rely on the sequence, they should have to specify the exact engine they want.

TL;DR: System.Random in C# should not ever have been seedable, big mistake.

Everyone knows about bit-fiddling functions, what the poster was referring to is using this trick to not have to store the capacity for a dynamic vector. Which is genuinely very clever and rare, I don’t think I’ve ever seen it done quite like this either. I think that’s probably because it’s not really that good of an idea, if the vector can shrink, you really should store the capacity.
It doesn’t really work though for generic vectors. If you support not just vec_push but vec_pop as well, then you really do need to store capacity separately or else call realloc way more often than you normally need to.
Re:Building an HTML-first site doubled our users overnight on Wednesday June 10, 2026 @11:37AM (#48478007)
As a non-web dev, I have a question about this part:

> There was a sad coda; as is the way of contract work, I moved on. I explained what I had built to my replacement, that it always worked even without javascript. He was appalled and said, “but that’s a lot more work for us.”

Why is it more work? The approach described in the article seems honestly reasonably simple: just write the standard <input> components for the form, have a submit button at the bottom. When I was making my own websites many years ago now, that's how it worked, and it wasn't that hard. Maybe it's reflecting my ignorance in this field, but doing fancy front-ends seems much harder to me.

Re:MacBook Neo Is So Popular That Apple Doubled Production on Wednesday June 03, 2026 @01:38PM (#48387084)
Not even young people: I have a very expensive MacBook Pro M5 i got from work, but my personal laptop is old and needs replacing. I’m a well-paid senior software developer and could afford any computer I wanted. But the MacBook Neo is a top contender even for me. I mostly need something for like editing documents, hobby coding and watching YouTube videos. It runs Codex or Gemini-CLI fine. For the price point, it seems perfect for a second computer. I could pay premium prices for something better, but honestly: I don’t think I need to.
Re:Why Janet? (2023) on Wednesday June 03, 2026 @09:35AM (#48383862)
Sure! The main formats are VST3 (from Steinberg, the most popular format), AU (from Apple, supported by most macOS hosts, and Logic only uses AU), AAX (for Avid Pro Tools) and CLAP (an open source variant, that's the best of all of them but is having trouble getting market share). Then there is also "Standalone", which is when you just run your plugin as a standalone app.

Because of this plethora of standards, most plugin developers (including us, I work at XLN Audio) use the JUCE C++ framework, which provides a uniform interface to all these formats and more. It's available on GitHub under a GPL license if you just want to play with it (it has excellent tutorials and example projects). If you're just curious about development thing, I recommend using Reaper as a host to test in, both because it's essentially free (it's free like WinRAR is free), and it has tons of options for how to run plugins (all in the main process, all in a bridged process, every plugin in a dedicated process, etc.).

Audio plugins are essentially dynamic libraries loaded at runtime, and a common way to run them (used to be universal, but some hosts are changing) is that the dynamic library is just loaded in the main process address space and the host communicates with it by calling functions on it. That means that if a single plugin (out of maybe dozens in a project) crashes, it takes the entire host down. In addition, if you have multiple instances of the same plugin (very common, you might have the same effect on multiple tracks, for instance), all global and thread_local variables are shared between them, which makes global variables a total nightmare, and raises the thread_local problem I mentioned earlier.

Our products use JUCE for the unified interface, but then we have an entirely custom Lua codebase for the GUIs and scripting the products themselves (with lots of connections to the audio engine, which is of course C++). There are very limited languages you can embed this way, because of the requirements I mentioned above. The ones I've looked at which you could possibly do it with is Lua, Python (3.12+), JavaScript and Tcl. I haven't done a lot of testing outside of Lua though, this is just me looking at the embedding APIs. You could also do it with web views, and recent versions of JUCE provides nice ways to do that.

I wouldn't do it with Janet if it uses thread local state this way, but maybe it works. It would definitely work if you spun up dedicated threads for each instance and communicated the events back and forth, but that seems like a bad idea.

Let me know if you have more questions, this is a very weird field of programming that most developers are not exposed to.

Older »