HNHacker News
TopNewBestAskShowJobs

lukasgelbmann

176 karma · joined January 29, 2018

submissionscomments
lukasgelbmann··on If-then-else had to be invented (2020)
What you probably won’t find, though, is the programmer’s else: “If X, Y. Else [meaning: if not X], Z.”
lukasgelbmann··on If-then-else had to be invented (2020)
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”.)

lukasgelbmann··on If-then-else had to be invented (2020)
> > 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”.

lukasgelbmann··on Apple's git still trusts the compromised eMudhra certificates
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.
lukasgelbmann··on Apple's git still trusts the compromised eMudhra certificates
> “This is being fixed now”

Wow, that was fast!

lukasgelbmann··on Apple's git still trusts the compromised eMudhra certificates
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.

lukasgelbmann··on Apple's git still trusts the compromised eMudhra certificates
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.

lukasgelbmann··on Ten days later, Git on macOS still trusts the compromised eMudhra certificates
Yes, it’s insane. Step 2 does next to nothing for security without step 3.
lukasgelbmann··on Apple's git still trusts the compromised eMudhra certificates
Homebrew’s git (unlike homebrew’s curl) seems to default to using the system’s CA bundle, not homebrew’s. Is that a bug?
lukasgelbmann··on Ten days later, Git on macOS still trusts the compromised eMudhra certificates
You could be running a different version of curl, e.g. homebrew. Try `which curl` and `/usr/bin/curl <url>`.
lukasgelbmann··on The Exponential Time Hypothesis Is False [pdf]
> “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

lukasgelbmann··on Speeding up code review with `small-change`
> “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”?

lukasgelbmann··on Type Safe Generic Data Structures in C (2025)
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.

lukasgelbmann··on UTF-8000: Unlimited UTF-8
Right, UTF-8000 does have this property. Too late to edit my comment now, thanks for noticing that.
lukasgelbmann··on UTF-8000: Unlimited UTF-8
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.

lukasgelbmann··on There's No Limit to How Bad Code Can Get
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

lukasgelbmann··on Don't stop early: Case-folding source code at memory speed
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.

lukasgelbmann··on Don't stop early: Case-folding source code at memory speed
There’s 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.

lukasgelbmann··on Ask HN: Who wants to be hired? (August 2026)

  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: me@lukasgelbmann.com
Senior software engineer, experienced with backend engineering, databases, data analytics, application security, web applications, and fullstack development.
lukasgelbmann··on Firefighter arson a long-standing issue – expert
> 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?)

lukasgelbmann··on A glitch in February of the year 0
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

lukasgelbmann··on Ask HN: What are you working on? (June 2026)
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

lukasgelbmann··on Bttf is a command line datetime Swiss army knife
> “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)
lukasgelbmann··on If more than 50% press blue, everyone survives. Red pressers always survive
With 3, especially if the animals outnumber humans, you’d first want to do some research into animal psychology to see whether red or blue has an edge for animals.
lukasgelbmann··on If more than 50% press blue, everyone survives. Red pressers always survive
There’s a moral benefit to choosing blue if you think there’s a chance that the end result will be split 50-50 and you’ll be the deciding vote between a blue majority and a red majority.
lukasgelbmann··on An AI agent deleted our production database. The agent's confession is below
If you’re using a model, it’s your responsibility to make sure the probability actually is that small. Realistically, you do that by not giving the model access to any of your bloody prod API keys.
lukasgelbmann··on GitHub's fake star economy
That’s not something I wanted to imply. It can also stand for "the fine article". Is there a better shorthand for "the article linked at top of the page" / "the original article"?
lukasgelbmann··on GitHub's fake star economy
I use stars to try and protect myself from dependency confusion attacks.

For example, let’s say I want to run some piece of software that I’ve heard about, and let’s say I trust that the software isn’t malware because of its reputation.

Most of the time, I’d be installing the software from somewhere that’s not GitHub. A lot of package managers will let anyone upload malware with a name that’s very similar to the software I’m looking for, designed to fool people like me. I need to defend against that. If I can find a GitHub repo that has a ton of stars, I can generally assume that it’s the software I’m looking for, and not a fake imitator, and I can therefore trust the installation instructions in its readme.

Except this is also not 100% safe, because as mentioned in TFA, stars can be bought.

lukasgelbmann··on No_color: Disabling ANSI color output by default
Does NO_COLOR=1 mean that all ANSI formatting should be disabled? Including bold text, italic text, and so on?

It seems that different software handles that question in different ways.

lukasgelbmann··on Python strings are immutable, but only sometimes
Joining on a list (as in function two()) is no more memory intensive than joining on a generator expression (function one()). This is surprising at first. Raymond Hettinger has a very good explanation.[0] In short, it's because "".join() needs to iterate over the elements twice, and so it needs to store the whole sequence of string anyway.

[0] https://stackoverflow.com/a/9061024

Page 1 of 2Next →