HNHacker News
TopNewBestAskShowJobs

rstuart4133

2,805 karma · joined March 28, 2014

submissionscomments
rstuart4133··on Robot beats humans to win Beijing half-marathon
I'm sure the humans would have done better, if there were allowed unlimited swaps as well. You can do amazing things with an unlimited energy budget.

The major innovation in this years winner was being able to do battery swaps without needing a 3 minute robot reboot.

rstuart4133··on The beginning of scarcity in AI
> imagine that a null pointer would mostly result from a malloc() or some other parts of the program failing, in which case would you not expect to see errors elsewhere?

Oh yes, you probably will see errors elsewhere. If you are lucky it will happen immediately. But often enough millions of executed instructions later, in some unrelated routine that had its memory smashed. It's not "fun" figuring out what happened. It could be nothing - bit flips are a thing, and once you get the error rate low enough the frequency of bit flips and bugs starts to converge. You could waste days of your time chasing an alpha particle.

I saw the author of curl post some of this code here a while back. I immediately recognised the symptoms. Things like:

    if (NULL == foo) { ... }
Every 2nd line was code like that. If you are wondering, he wrote `(NULL == foo)` in case he dropped an `=`, so it became `(NULL = foo)`. The second version is a syntax error, whereas `(foo = NULL)` is a runtime disaster. Most of it was unjustified, but he could not help himself. After years of dealing with C, he wrote code defensively - even if it wasn't needed. C is so fast and the compilers so good the coding style imposes little overhead.

Rust is popular because it gives you a similar result to C, but you don't need to have been beaten by 10 years of pain in order to produce safe Rust code. Sadly, it has other issues. Despite them, it's still the best C we have right now.

rstuart4133··on The beginning of scarcity in AI
> I always found myself writing verbose copypasta code first, then compress it down based on the emerging commonalities. I think doing it the other way around is likely to lead to a worse design.

I do pretty much the same thing, which is to say I "write code using a brain dump", "look for commonalities that tickle the neurons", then "refactor". Lather, rinse, and repeat until I'm happy.

> Can you not tell the LLM to do the same?

You can tell them until you're blue in the face. They ignore you.

I'm sure this is a temporary phase. Once they solve the problem, coding will suffer the same fate as blacksmiths making nails. [0] To solve it they need to satisfy two conflicting goals - DRY the code out, while keeping interconnections between modules to a minimum. That isn't easy. In fact it's so hard people who do it well and can do it across scales are called senior software engineers. Once models master that trick, they won't be needed any more.

By "they" I mean "me".

[0] Blacksmiths could produce 1,000 or so a day, but it must have been a mind-numbing day even if it paid the bills. Then automation came along, and produced them at over a nail per second.

rstuart4133··on U.S. set to launch tariff refund system on April 20
The true irony is 10% .. 15% of importers to the USA (Importer of Record in the lingo) are foreign entities. For them, the tariff refund is a transfer directly from the USA consumer to the foreign countries ... that Trump was trying to penalise.
rstuart4133··on The beginning of scarcity in AI
Yes `foo` is a pointer.

`free(NULL)` is harmless in C89 onwards. As I said, programmers freeing NULL caused so many issues they changed the API. It doesn't help that `malloc(0)` returns NULL on some platforms.

If you are writing code for an embedded platform with some random C compiler, all bets on what `free(NULL)` does are off. That means a cautious C programmer who doesn't know who will be using their code never allows NULL to be passed to `free()`.

In general, most good C programmers are good because they suffer a sort of PTSD from the injuries the language has inflicted on them in the past. If they aren't avoiding passing NULL to `free()`, they haven't suffered long enough to be good.

rstuart4133··on The beginning of scarcity in AI
I used LLMs to write what seems like far too many lines of code now. This is an example Opus 4.6 running at maximum wrote in C:

    if (foo == NULL) {
       log_the_error(...);
       goto END;
    }
    END:
    free(foo);
If you don't know C, in older versions that can be a catastrophic failure. (The issue is so serious in modern C `free(NULL)` is a no-op.) If it's difficult to get a `FOO == NULL` without extensive mocking (this is often the case) most programmers won't do it, so it won't be caught by unit tests. The LLMs almost never get unit test coverage up high enough to catch issues like this without heavy prompting.

But that's the least of it. The models (all of them) are absolutely hopeless at DRY'ing out the code, and when they do turn it into spaghetti because they seem almost oblivious to isolation boundaries, even when they are spelt out to them.

None of this is a problem if you are vibe coding, but you can only do that when you're targeting a pretty low quality level. That's entirely appropriate in some cases of course, but when it isn't you need heavy reviews from skilled programmers. No senior engineer is going to stomach the repeated stretches of almost the "same but not quite" code they churn out.

You don't have to take my word for it. Try asking Google "do llm's produce verbose code".

rstuart4133··on The beginning of scarcity in AI
> I've seen this claimed, but I'm not sure it's been true for my use cases?

I'd be surprised if it isn't true for your use cases. If you give GLM-5.1 and Optus 4.6 the same coding task, they will both produce code that passes all the tests. In both cases the code will be crap, as no model I've seen produces good code. GLM-5.1 is actually slightly better at following instructions exactly than Optus 4.6 (but maybe not 4.7 - as that's an area they addressed).

I've asked GLM-5.1 and Opus 4.6 to find a bug caused by a subtle race condition (the race condition leads to a number being 15172580 instead of 15172579 after about 3 months of CPU time). Both found it, in a similar amount of time. Several senior engineers had stared at the code for literally days and didn't find it.

There is no doubt the models do vary in performance at various tasks, but we are talking the difference between Ferrari vs Mercedes in F1. While the differences are undeniable, this isn't the F1. Things take a year to change there. The performance of the models from Anthropic and OpenAI literally change day by day, often not due to the model itself but because of the horsepower those companies choose to give them on the day, or them tweaking their own system prompts. You can find no end of posts here from people screaming in frustration the thing that worked yesterday doesn't work today, or suddenly they find themselves running out of tokens, or their favoured tool is blocked. It's not at all obvious the differences between the open-source models and the proprietary ones are worse than those day to day ones the proprietary companies inflict on us.

rstuart4133··on The buns in McDonald's Japan's burger photos are all slightly askew
I gave up on the app completely when I placed an order via the app, was waved past the payment window, then the order window denied it was placed (and paid for). I showed them the phone with the order number still on it. They said it could be a screenshot. After arguing for a while, I drove away without food.

I eventually got a refund after digging throw their web site for an email address, and emailed them the statement showing where it has been paid. With the back and forward while they asked for evidence, it took over an hour of my time in the end to get the refund. It wasn't the money. It was the principle.

The app is by far the slowest, most unreliable way to place an order with them. Period. The next slowest (although far better) is the kiosks. They also unreliable when the printer doesn't work (which is most of the time), and you make the mistake of forgetting the receipt number. Other fast food outlets have solved this problem by getting you to enter your name. That's beyond McDonalds apparently. The fastest, and most reliable way by far is to talk to a human.

The order should be the reverse. It is beyond me how they get it so badly wrong. Maybe price discrimination is the reason. Nothing else makes much sense for an organisation of the size and resources of McDonalds.

rstuart4133··on jj – the CLI for Jujutsu
> https://github.com/jj-vcs/jj/issues/5596 doesn't seem to be the oldest instance of this problem, but does seem to be the current discussion, and there seems to be no consensus on how to fix.

Ahh, sorry - I didn't understand the issue. Yes, that is going to catch you unawares.

I can't see a better solution than a warning. It looks to be an unavoidable negative side effect of jj's auto-commit behaviour, but auto-commits bring so many positives I'll wear the occasional stray add. Usually they are harmless and trivial to reverse - but I've made a mental note to revise my jj workflow. When I change .gitignore, do it in the oldest mutable commit.

> Oh, and ISTR submodules were a pain to work with.

Yes, they are, although that's no different to git. JJ's tracking of submodule hashes in the parent repository behaves exactly as you would expect. What jj doesn't have is a command to bring the submodule into sync with the parent repository, like git's submodule command.

However, I find git's submodule command behaviour borders on inexplicable at times. I wrote my own `jj submodule` alias that does one simple job - it checks out every submodule the parent repository owns, at the hash recorded by the parent. I find that far better than the git command, which follows the usual git pattern of being a complex mess of sub-sub-commands with a plethora of options.

If jj automatically recursively updated submodules when you moved to a different change-id, it would be most of the way there. If it added commands to add and remove submodule directories, it would be there, and the reasons people dislike git's submodules would be gone.

rstuart4133··on jj – the CLI for Jujutsu
There is some truth to that, but to give a different perspective ...

A long, long time ago, back when VCS's were novel enough to be of academic interest, I read numerous papers describing what these VCS's could be. They talked in terms of change sets, and applying them like a calculus to source code. In the meantime those of us writing code people actually used were using sccs and rcs, or if you were really unlucky Visual SourceSafe. To us in the trenches those academics were dreamers in ivory towers.

With the passage of time we got new VCS that gradually knocked the rough edges off thoase early ones. svn gave us atomic commits, hg gave us a distributed VCS, git gave us that plus speed. But none came close to realising the dreams of those early academics. It seemed like it was an impossible dream. But then along came jj ... and those dreams were realised.

rstuart4133··on jj – the CLI for Jujutsu
They do publish binaries they work perfectly well on Linux. No need for cargo:

https://github.com/jj-vcs/jj/releases/tag/v0.40.0

rstuart4133··on jj – the CLI for Jujutsu
> Except there isn't any concept of a remote jj so you have to go through the painful steps of manually naming commits, pushing, pulling, then manually advancing the current working point to match.

All true. I ended up writing my own `jj push` and `jj pull` aliases that automated all this. They aren't simple aliases, but it worked. `jj push` for example "feels" very like `git push --force-with-lease`, except if you've stacked PR's it pushed all branches your on. It hasn't been a problem since.

I ended up wondering if they deliberately left the `jj pull` and `jj push` commands unimplemented just so you could write something custom.

> All files automatically committed is great until you accidentally put a secret in an unignored file in the repository folder.

    jj abandon COMMIT && jj git garbage-collect
> And adding to .gitignore fails if you ever want to wind back in history - if you go back before a file was added to .gitignore, then whoops now it isn't ignored

True, but how is this different to any other VCS?

rstuart4133··on jj – the CLI for Jujutsu
What makes jj better requires a mindset change. When you start with jj, you use it as an alternate porcelain for git, meaning you just use the jj commands that map to the way you used git. You have to let go of that mindset. Until you do, you are still using those old git commands; they are just have prettier clothing. The prettier clothing is not worth the effort.

I don't know how to explain a mindset to you, so I'll give one example of something that sounds so grand, it seems impossible. (There are so many unusual aspects to jj, but hopefully this is one you can immediately relate to.) Git famously makes it hard to lose work, but nonetheless there are commands like `git reset --hard` that make you break out in a sweat. There is no jj command that destroys information another jj command can't bring back. And before you ask - yes of course jj has the equivalent of `git reset --hard`.

rstuart4133··on jj – the CLI for Jujutsu
I'm not sure what you are asking, but you want to look at how a particular jj change-id evolved over time, use `jj evolog`. By default that evolution is hidden. The `change-id/N` syntax has uses beyond conflicts.
rstuart4133··on jj – the CLI for Jujutsu
> Obviously I can’t argue against your lived experience, but it is neither typical nor common.

I consider myself a proficient jj user, and it was my lived experience too. Eventually you get your head around what is going on, but even then it requires a combination of jj and git commands to bring them into sync, so `jj status` and `git status` say roughly the same things.

The friction isn't that jj handles state differently, it's that `jj git export` doesn't export all of jj's state to git. Instead it leaves you in a detached HEAD state. When you are a newbie looking for reassurance this newfangled tool is doing what it claims by cross checking it with the one you are familiar with, this is a real problem that slows down adoption and learning.

There are good reasons for `jj git export` leaving it in a detached head state of course: it's because jj can be in states it can't export to git. If we had a command, say `jj git sync` that enforced the same constraints as `jj git push` (requiring a tracked branch and no conflicts) but targeted the local .git directory, it would bridge the conceptual gap for Git users. Instead of wondering why git status looks wrong, the user would get an immediate, actionable error explaining why the export didn't align the two worlds.

rstuart4133··on jj – the CLI for Jujutsu
> and it does, in my understanding, work.

I use submodules with jj, and jj saves and restores submodule hashes perfectly. What it doesn't do is manipulate the sub-repository from its parent. You can do that yourself using jj or git of course, which is what I ended up doing using a few scripts. The result ended up being more reliable than using git's submodule commands directly.

They can take all the time in the world to implement submodules as far as I'm concerned. jj's implementation of workspaces removes all of the hairs of git's worktrees. git submodule implementation has even more hairs than worktrees. If the jj developers need time to do as good a job on submodules as they did with workspaces, then I say give it to them.

rstuart4133··on jj – the CLI for Jujutsu
> so you need to defensively create empty new commits for your changes.

I thought that for a long while too, and was equally pissed. Then I happened upon `jj evolog`. Turns out jj had a better solution than staging all along - I just didn't realise it existed.

The move from using jj as an alternate porcelain to git to using it efficiently took me more months than I care to admit. I suspect being familiar with git cli is actually a handicap in learning jj. New users without pre-conceptions will have a much easier time of it.

And oddly, I also suspect they will also end up knowing more about the underlying git storage engine than git users. It turns out it's capable of being used far more effectively than git uses it.

Doubly oddly, I blame Linus's familiarity with CVS and SVN for that. He (correctly) bemoaned how unsuited to the job of distributed source code management they were and invented a storage engine that has proved to be remarkably good at the job. But he carried across many the concepts in their CLIs to gits porcelain. Jj (with a lot of help from hg), finally broke free of that legacy.

rstuart4133··on In Denmark, the spread of solar panels has become a divisive issue
A quick calculation shows to supply all of Denmark's energy needs with solar, (assuming sufficient storage), they would need about 1,000 km² of solar panels. That's about 2% of their land area. That assumes a solar irradiation rate of 0.5 kWh / m² which is about what they get in winter. They get 6 kWh / m² in summer, so there would be 10 fold over production then. If they stored that by converting it to hydrogen, even if done very inefficiently, it would more than halve the land area required.

Given their solar irradiation is so poor they would be better off with wind. While 2% is big, it isn't inconceivable, particularly as solar panels don't prevent the land from being used for other things, such as transport, buildings, even some forms of agriculture. People will get comfortable with it over time, just as they did with destroying most natural ecosystems in Europe to turn the land over to agriculture. That horrifies me far more than covering 2% of land with solar panels.

rstuart4133··on The economics of software teams: Why most engineering orgs are flying blind
> They can help with those tasks because there are decades of published research on them.

No.

I suspect the underlying meme behind this is "LLMs can't think, they are just stochastic parrots". If you define an LLM to be the thing the model builders train by ingesting and compressing information on the internet, in a way that yields a very convenient if somewhat unreliable search engine, then that's true. But if you define them that way, the modern models like Opus, Gemini, GLM and so on aren't pure LLMs, and haven't been for a while. They still have an LLM inside them, but have other things bolted on like attention heads, context windows, and Chain of Thought. These things outperform humans at some tasks that require "thinking".

Glasswing is an example. Before Glasswing human "researchers" could find a solution to a particular problem, the "lets find an exploit in this software" problem, as a particular rate. Now with Glasswing, it's orders of magnitude faster than that rate. The same thing has happened in other areas, like protein folding and weather prediction. These models aren't reproducing something they've seen before. They are producing things we consider new - like creating an exploit for a vulnerability they discovered.

With all the evidence around if you are still hanging onto the idea these models can't help with many tasks by doing what we call "thinking", you are in denial.

rstuart4133··on GitHub Stacked PRs
`git reset --hard` destroys uncommitted changes. There is no git command to recover those files. JJ has a similar command of course, but it saves the files to a hidden commit before changing them.
rstuart4133··on GitHub Stacked PRs
> But there's the reflog in git which is the ultimate undo tool.

That one sentence outs you as someone who isn't familiar with JJ.

Here is something to ponder. Despite claims to the contrary, there are many git commands that can destroy work, like `git reset --hard`. The reflog won't save you. However there is literally no JJ command that can't be undone. So no JJ command will destroy your work irretrievably.

rstuart4133··on Make tmux pretty and usable (2024)
> Zellij is close to 50 megabytes,

That's a Rust thing. It's what happens when you statically link because you monomorphise everything.

rstuart4133··on The economics of software teams: Why most engineering orgs are flying blind
It's true that we often split software engineering into two pieces: doing the design and implementing the code. In fact I often prefer to think of it as computer systems engineering because the design phase often goes well beyond software. You have to think about what networks are used, what the hardware form factor should be used, even how many check digits should be put on a barcode.

But then you go onto say this:

> But that is not programming then? Doing voice recognition in the 90s, missile guidance systems, you name it, those are hard things, but it's not the "programming" that's hard. It's the figuring out how to do it. The algorithms, the strategy, etc.

That implies LLMs can't help with design of something that needs voice recognition and missile guidance systems. If that's your claim, it's wrong. In fact they are far better at being sounding boards and search engines than they are at coding. They make the same large number of mistakes in design tasks as they do in software coding, but in design tasks the human is constantly in the loop, examining all of the LLM's output so the errors don't matter so much. In vibe coding the human removes themselves from the loop to a large extent. The errors become shipped bugs.

rstuart4133··on Android now stops you sharing your location in photos
I suspect this horse has bolted. When I see a photo on a website and I want to know where it's taken, I assume it's been stripped already and ask an AI. The accuracy is uncanny.

Since it's a rare web site that leaves the EXIF data intact, I guess this is aimed at apps harvesting photos on the device itself. I hope Firefox gets a new site permission that allows you to upload photos with the EXIF intact, because that's often what I want. But that won't happen for a while, and until apps do get their permissions updated it's going to be annoying. It will be a right proper PITA to discover later your EXIF data is gone from the photos you transferred to your laptop.

rstuart4133··on Seven countries now generate nearly all their electricity from renewables (2024)
There is pushback here against the figures you are quoting.

Here is something real. South Australia electricity production averaged 75% from renewables last year. Wikipedia (for 2023) put it at 70%: "70 per cent of South Australia's electricity is generated from renewable sources. This is projected to be 85 per cent by 2026, with a target of 100 per cent by 2027." https://en.wikipedia.org/wiki/Energy_in_South_Australia They averaged 75% in 2025.

South Australia has no hydro to speak of. They have a some local gas, but no local coal. They do have good wind and solar resources. To me it looks like the transition was driven largely by immediate pragmatism concerns, as renewables are so much cheaper than gas. The politicians make a lot of noise about it of course, but I suspect if they had a local cheap source of coal the outcome would have been different.

Their electricity prices are high by Australian standards - but they have to pay for the gas they import to cover the missing 25%, and gas is by far the most expensive form of generation in Australia. And they are paying for all the new equipment this transition requires.

rstuart4133··on Git commands I run before reading any code
As someone else said, jj comes into its own when a reviewer insists you split your PR into many commits, because they don't want to review 13k lines in one chunk. In that case it is easier because there is no rebase. To change a PR commit in the middle of the stack you checkout a PR commit, edit it - and done. The rebase happened automagically.

Notice I didn't say "edit it, commit, and done" because that's another thing you don't do in jj - commit. I know, `git commit` is just a few characters on the cli - but it's one of several git commands you will never have to type again because jj does it without having to be asked.

If the rebase created a merge conflict (it could do so in any PR commit above the one you edited) - it's no biggie because jj happily saves merge commits with conflicts. You just check it out, and edit to remove the conflict.

Jj does grow on you over time. For example, when you start with jj you end up in the same messes you did as a git beginner, when you recovered with 'rm -r repository', followed by 'git clone git@host/repository.git'. Then you discover 'jj op restore' which compared to git's reflog is a breath of fresh air. And while you might at first find yourself chafing at the loss of git staging, you gradually get comfortable with the new way of working - then you discover `jj evolog`, and it's "omg that's far better than staging". Ditto with workspaces vs worktrees, and just about everything else. It might be difficult to lose work with a bad git command, but actually impossible to lose work with a jj command.

It is a steep learning curve. We are talking months to use it fluently instead of treating it as git with better porcelain. If all you ever do is work with one commit at a time, it's a lot of effort for not a lot of return. But as soon as you start managing stacks of changes, duplicating them, splicing them, it makes you feel like a god.

That said, if you are starting out - I'd suggest starting with jj instead of git. You've got to go through a learning curve anyway. You may as well do it with the kinder, gentler, more powerful tool.

rstuart4133··on Issue: Claude Code is unusable for complex engineering tasks with Feb updates
I got a similar response. It looked wrong on several levels. So I asked it: if it knew the current time, and if it hard learnt when I retire.

It claimed it didn't know either.

rstuart4133··on The threat is comfortable drift toward not understanding what you're doing
My own version of this is that I wanted bank transactions in CSV format. However, the transactions were more than a year old, and the bank only provides recent transactions in a downloadable form. They do, however, provide statements in PDF format going back indefinitely. But the objects in the PDF are arranged in a way that made pdftotext output near-indecipherable.

I thought I'd give Gemini a go. When I uploaded the 18-page PDF, it complained the output exceeded some limit. So I used pdftk to break it up into 4-page chunks, which seemed to work - the output looked very good and passed a couple of spot checks. But I don't trust these things as far as I can kick them.

There was a transaction column and a running balance column, so I did a quick check to see if every new balance equalled the previous one plus the transaction. And it almost always did. There were a couple of errors I put down to transcription errors. I was wrong. I eventually twigged that these errors only happened where I had split the PDFs. After tracking where the balance first went wrong, it became evident it had dropped chunks of lines, duplicated others, and misaligned the transaction and balance columns. It was complete rubbish, in other words.

So why did my balance check show so few errors? I put that down to it knowing what a good bank statement looked like. A good bank statement adds up. So it adjusted all the balances so it looked like a real bank statement. I also noticed these errors got more frequent in later pages. I tried splitting the PDF into single pages and loading them into the model one at a time. That didn't help much for the later pages, but the first one was usually good. So then I loaded each page into a fresh context, with a fresh prompt. If that didn't produce something that balanced, the second go always did.

I'm not sure it saved time over doing it manually in the end. It's a tired analogy now, but it's true: at their heart, these things are stochastic parrots. They almost never produce the same output twice when given the same input. Instead, they produce output that has a high probability of following the input tokens supplied. If there is only one correct output but the output is small enough, the odds are decent they will get it right. But once the size grows, the odds of it outputting complete crap become a near certainty.

rstuart4133··on Ask HN: Where have you found the coding limits of current models?
> “good” API design (highly subjective)

A good API does two things. Firstly it DRYs the code out. Many APIs start life doing only that, as a collection of routines you get tired of writing over and over again. Secondly, the functions are designed in a way that reduces the need to share information. Typically they do that by hiding a whole pile of details in their implementation so knowledge of those details is all in one place rather than scattered across a code base. A term often used for APIs that don't do that well is "leaky", or we say it's a "leaky abstraction".

Perhaps a good API has other more subjective attributes but it must have those two. LLMs suck at both. You can see that in the comments here, when people say they write verbose code. It's verbose because the LLM didn't go looking for duplicated functionality - if it needed it, it just put the code where it was focused on at the time.

If they are bad at DRY then I need a better superlative to describe how they fare at respecting the isolation boundaries that underpin good module design. As far as I can tell, they have no idea about the concept or how to implement it. Let loose, they are like a bull in a china shop, breaking one boundary after another.

rstuart4133··on FCC updates covered list to include foreign-made consumer routers
> I suggest reading up on wifi and RF before going further.

I'd suggest neither matter in the face of how the problem is solved in the consumer cards the OP was talking about. They solve it by locking down the firmware that controls the radios.

The reality is most routers do that too. You can replace the firmware in most of them with OpenWRT or something similar. You still can't exceed regulatory limits because of the signed blobs of firmware in the radios.

Nonetheless, here we are getting comments like yours, which imply all firmware in the device must be behind a proprietary wall because a relatively small blob of firmware in them must be protected. It has its own protections. It doesn't need to be protected by the OS or the application that runs on top of it.

Yet it's in those applications where most of the vulnerabilities show up. Making them consumer replaceable would help in solving the problem. Protecting the firmware is not a good reason to not do it.

← PreviousPage 7 of 34Next →