News for hackers. Stuff that matters.

lukasgelbmann

What you probably won’t find, though, is the programmer’s else: “If X, Y. Else [meaning: if not X], Z.”
I think it’s a different construction.

The programmer’s if-else goes like “If the window is open, close it. Else, leave it closed.” This is not a natural construction outside of programming, people would use “otherwise” or “if not” instead.

(“Else” stands for “if the window is not open” in the above.)

The Crime and Punishment if-else is more like “If the window is open, close it. Else, cold air will enter.” This is normal English.

(“Else” stands for “if you don’t close it” here. It can’t stand for “if the window is not open”.)

> > Perhaps it will all come back, but now if you love me, give me up . . . else I shall begin to hate you, I feel it.

It’s not being used in the programming if-else sense here. He’s not saying “if you don’t love me, I shall begin to hate you”. He’s saying “if you don’t give me up, I shall begin to hate you”.

Ah, you’re right. Though unless I’m mistaken again, Safari (but not Chrome and Firefox) still trusts AAA Certificate Services and handles this issue with revokations.
> “This is being fixed now”

Wow, that was fast!

I think the main problem is that the weak eMudhra intermediates were cross-signed by Sectigo. Certificate revokations are needed to handle this correctly.

Dropping the Sectigo root along with the eMudhra root is the easy and safe solution, and maybe this is what Apple should have done (it’s the workaround they recommend!). But it means that some small percentage of certificates that are fine won’t be accepted.

Chrome dropped one of the eMudhra roots. The problem is that the weak eMudhra intermediates were cross-signed by Sectigo. ~~Browsers (at least Chrome) didn’t drop the Sectigo root, instead they store a revokation for the cross-signature.~~ (edit: this is wrong, see josephcsible’s answer below)

Dropping the Sectigo root along with the eMudhra root is the easy and safe solution, but it means that some small percentage of certificates that are fine won’t be accepted.

Yes, it’s insane. Step 2 does next to nothing for security without step 3.
Homebrew’s git (unlike homebrew’s curl) seems to default to using the system’s CA bundle, not homebrew’s. Is that a bug?
You could be running a different version of curl, e.g. homebrew. Try `which curl` and `/usr/bin/curl <url>`.
Re:The Exponential Time Hypothesis Is False [pdf] on Tuesday October 27, 2026 @04:18AM (#50255995)
> “We had O(n lg n) since 2019 already”

Yes, svat’s comment accounts for that by using little-o notation* in o(n log n). This was only achieved in the 2026 result.

* https://en.wikipedia.org/wiki/Little_o_notation

Re:Speeding up code review with `small-change` on Friday October 23, 2026 @06:24AM (#50206792)
> “Impacts fewer than N distinct services or applications. N is 1 on our frontend monorepo[…]”

What kind of change impacts fewer than 1 services or applications? Is this meant to say “at most N”?

Re:Type Safe Generic Data Structures in C on Monday October 05, 2026 @12:09PM (#49966748)
Yes, and variable length arrays were made an optional part of the standard in C11. Whereas flexible array members remain a standard required feature.

Flexible array members don’t allocate a dynamic amount of memory on the stack.

Re:UTF-8000: Unlimited UTF-8 on Sunday September 20, 2026 @09:39AM (#49775764)
Right, UTF-8000 does have this property. Too late to edit my comment now, thanks for noticing that.
Re:UTF-8000: Unlimited UTF-8 on Sunday September 20, 2026 @04:38AM (#49773813)
Self-synchronization in UTF-8 is intuitively a great thing to have, yet I don’t remember actively relying on it ever. Does anyone have a good example of when it‘s useful?

Another related nice property that UTF-8 has: substring search reduces to bytestring substring search. I.e. given two Unicode strings in UTF-8 encoding, you can check if one is a substring of the other by just treating them as bytestrings and checking if one bytestring is a substring of the other bytestring. This is a stronger property than self-synchronization: UTF-8 has it, but UTF-8000 doesn’t.

Re:There's No Limit to How Bad Code Can Get on Saturday September 05, 2026 @02:52PM (#49579502)
Insightful article. The author makes some great points about the dynamics of technical debt in organizations.

I think a sinking ship is a reasonably good metaphor though. A sunken ship is a horrible, terrible outcome.

In the metaphor, a codebase is sunken when it’s unviable to continue using it. The organization stops working on it and no longer runs it. At this point, the code is completely worthless to the business, like a ship at the bottom of the ocean. True, you could imagine the code getting worse theoretically. But in reality, it will just sit there and rot.[0] The business might attempt a rewrite or just discontinue the product.

It’s possible, but not a given, that a business sinks with one of its codebases. This can happen with a ship too, if a business relies heavily on it.

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

Re:Don't stop early: Case-folding source code at memory speed on Wednesday August 05, 2026 @02:45AM (#49179376)
Too late to edit, but the situation with İ is more complicated, and I got the mapping wrong for this specific casefold implementation.

What I should have said is that in the case of İ/i/I/ı, using str::to_lowercase for string matching wouldn’t be any less correct than using their locale-independent casefold.

The third character in the list, final sigma, is a good example that illustrates why using str::to_lowercase for string matching isn’t good.

Re:Don't stop early: Case-folding source code at memory speed on Wednesday August 05, 2026 @12:15AM (#49178496)
There some interesting information in there. Unfortunately the person or LLM writing this got pretty confused right in the introduction already.

> “Suppose […] they type straße and you’ve stored STRASSE. To make these count as matches, you need […]”

Really bad example, because as the article says later on, this casefold crate won’t match those two strings because the ß → ss conversion isn’t done.

> “[str::to_lowercase and case folding] diverge on real characters—ß, İ, final sigma”

The main point is true (case folding is different from lowercasing), but two of the three examples are wrong. The casefold operation that they use maps ß to itself, as does str::to_lowercase. The casefold operation maps İ to U+0069 U+0307 regardless of locale, as does str::to_lowercase.

When I’m reading an article, these kind of mistakes in the introduction make me doubt the accuracy of the whole article. Which is a shame, because again, it’s an interesting write-up. The mistakes also make the article harder to follow, since the examples imply ß is folded to ss.

Re:Ask HN: Who wants to be hired? (August 2026) on Monday August 03, 2026 @01:00PM (#49158451)

  Location: Europe (UTC+2)
  Remote: yes
  Willing to relocate: no
  Technologies: Python, SQL, C, Java, Go, PHP, JavaScript, Typescript, Claude Code, Analytics, Git
  LinkedIn: https://linkedin.com/in/lukas-gelbmann
  Email: [email protected]
Senior software engineer, experienced with backend engineering, databases, data analytics, application security, web applications, and fullstack development.
Re:About 100 firefighters are convicted of arson, every year on Saturday August 01, 2026 @02:07AM (#49131544)
> There are 349 million people in the US, so the number of arsonists is 0.0001% of the general population. The number of firefighters that are arsonists (100/65,795) is 0.0015%, so I suppose it's slightly higher that the general population.

You comparing arsonists/pop with firefighter-arsonists/arsonists. That’s the wrong comparison. You should be comparing arsonists/pop with firefighter-arsonists/firefighters. Or firefighters/pop with firefighter-arsonists/arsonists.

(On top of that, mixing numbers from different sources can be problematic. For example, how are repeat convictions treated in the different sources? Who counts as a firefighter?)

Re:A glitch in February of the year 0 on Sunday July 05, 2026 @02:16PM (#48796493)
Author here.

Our aim isn’t to try and line up with the calendar that was in use at the time, 2026 years ago.

Instead, the aim (for 28times) is to implement the rules of the proleptic Gregorian calendar[0] correctly. The bug was that those rules weren’t followed for some rare values.

But to address your comment properly, I think I should justify why on Earth someone would want to use the proleptic Gregorian calendar for year 0 and before. In short, because it’s a useful fiction.

The biggest reason is interoperability: a lot of software follows proleptic Gregorian rules, aligning around ISO 8601. Probably a clear majority of date/time software. We want to line up with all that existing software that assigns a specific meaning to a string like "0000-02-01". That’s the first of February in the proleptic Gregorian calendar, even though it was a different date in the ancient Romans’ calendar.

The other reason is to keep it simple: since most people use the Gregorian calendar in present times, it’s simplest (for us as implementors, but also for users) to extend its rules into the distant past and distant future. The alternative for be to have multiple sets of rules, e.g. Julian and Gregorian calendar. (You might say it would be even simpler to just not allow timestamps before 1582. But there are use cases, e.g. in astronomy or history, where people want to work with timestamps before 1582, and even before 1 AD.)

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

Re:Ask HN: What are you working on? (June 2026) on Sunday June 14, 2026 @02:03PM (#48530510)
I’m working on a time series management & analysis tool. The goal is to provide simple ways to work with time series data, including an API and visualisation.

https://28times.com

Re:Biff is a command line datetime Swiss army knife on Thursday May 28, 2026 @02:44PM (#48313565)
> “If you run this on a big repository, it will take quite a lot of time because `git log -n1` takes a long time. I think this is the fastest way to get the most recent commit time on a single file? (That's the assertion that I hope someone can correct me on!) In any case, `bttf tag exec` is using parallelism under the hood to make this even faster.”

Instead of running `git log -n1` on every file, I think you can walk through the commits backwards, skipping any files that have been seen. Something like this (these two commands could be followed by bttf commands):

  git log --pretty=format:"DATE:%aI" --name-only |
  awk '/^DATE:/ {date=substr($0, 6); next} $0!="" && !seen[$0]++ {print date, $0}'
This seems to run much faster. The only problem is it'll include files that have been renamed or removed. I got an AI to fix that too, but it starts getting awkward (still fast though!):

  git ls-files |
  awk '
    # Read all existing files from git ls-files into an array
    NR==FNR { lsfiles[$0]; next }

    # Process the git log stream
    /^DATE:/ { date=substr($0, 6); next }
    $0!="" && ($0 in lsfiles) && !seen[$0]++ { print date, $0 }
  ' - <(git log --pretty=format:"DATE:%aI" --name-only)

Older »