HN user

judofyr

6,746 karma

Programmer. judofyr@gmail.com @judofyr http://judofyr.net/

Posts35
Comments935
View on HN
t.holmium.no 1y ago

Comparing the Performance of Hk and Lefthook

judofyr
2pts0
t.holmium.no 4y ago

The Art of Comparing Apples with Oranges (or: DragonflyDB vs. Redis)

judofyr
2pts1
github.com 6y ago

Password Manager Resources (From Apple)

judofyr
2pts0
scrimba.com 8y ago

Learn CSS Flexbox for free through interactive screencasts

judofyr
17pts3
scrimba.com 8y ago

Learn CSS Grid through interactive screencasts

judofyr
206pts40
scrimba.com 8y ago

How we run NPM packages in the browser

judofyr
97pts30
imba.io 10y ago

Imba: A new programming language for web apps

judofyr
206pts128
imba.io 10y ago

Imba – A new programming language for the web

judofyr
319pts171
www.tail-f.org 13y ago

How to deal with negativity on Twitter

judofyr
32pts20
timelessrepo.com 14y ago

Abstraction Creep

judofyr
29pts6
www.youtube.com 14y ago

MemoryDealers CEO bets $10,000 on BTC outperforming gold, silver by 100x

judofyr
1pts0
reply.judofyr.net 15y ago

Why Windows 8 Isn't a Direct Response to the iPad

judofyr
6pts0
timelessrepo.com 15y ago

JSON: The JavaScript subset that isn't

judofyr
157pts35
timeless.judofyr.net 15y ago

Mockup-Driven Development

judofyr
19pts5
timeless.judofyr.net 15y ago

Charging Objects in Ruby

judofyr
56pts23
timeless.judofyr.net 15y ago

Follow-up: Why there is no talent

judofyr
13pts4
timeless.judofyr.net 15y ago

There is no talent

judofyr
158pts140
timeless.judofyr.net 15y ago

Refinements in Ruby — Monkey patching for friendly monkeys

judofyr
64pts11
www.pcisecuritystandards.org 15y ago

PCI Data Security Standards Rock (video)

judofyr
2pts0
the-least-surprised.judofyr.net 16y ago

The Least Surprised (Ruby comic by _why)

judofyr
50pts16
news.ycombinator.com 16y ago

Ask HN: Any startups working on education?

judofyr
3pts0
judofyr.net 16y ago

Implementing Exception#continue in Ruby

judofyr
5pts1
judofyr.net 16y ago

Temple - Template compilation framework in Ruby

judofyr
1pts0
ruby-std.netlab.jp 16y ago

Ruby Draft Specification

judofyr
23pts6
ventureiq.stackexchange.com 16y ago

VentureIQ - Stack Overflow for startups and entrepreneurs

judofyr
2pts0
www.reddit.com 16y ago

Who need XSS when you can simply ask?

judofyr
43pts25
jrubyconf.com 16y ago

JRubyConf - The day after RubyConf

judofyr
1pts0
blog.rubybestpractices.com 17y ago

Symmetry in method names

judofyr
6pts1
github.com 17y ago

GitHub.js

judofyr
1pts0
chromeshorts.com 17y ago

Chrome Shorts

judofyr
1pts0

Not sure where I picked up this, but I’ve added this to my global Git ignore:

    attic
That way you can just create an attic directory in any project where you can keep random stuff that should never be committed. I’ve yet to find a repo which actually has such a directory checker in.

Ignoring the misuse of epsilon, I'd also say that you'd be helping your users more by not providing a general `assert_f64_eq` macro, but rather force the user to decide the error model. Add a required "precision" parameter as an enum with different modes:

    // Precise matching:
    assert_f64_eq!(a, 0.1, Steps(2))
    // same as: assert!(a == 0.1.next_down().next_down())

    // Number of digits (after period) that are matching:
    assert_f64_eq!(a, 0.1, Digits(5))

    // Relative error:
    assert_f64_eq!(a, 0.1, Rel(0.5))

This is just wrong. See https://en.cppreference.com/w/cpp/atomic/memory_order.html. Emphasis mine:

A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store. All writes in the current thread are visible in other threads that acquire the same atomic variable (see Release-Acquire ordering below) and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic (see Release-Consume ordering below).

Very cool project! Always happy to see more work around static analysis.

However, looking at the recent commits it doesn't quite look like the most solid foundation: https://github.com/shuaimu/rusty-cpp/commit/480491121ef9efec...

    fn is_interior_mutability_type(type_name: &str) -> bool {
        type_name.starts_with("rusty::Cell<") ||
        type_name.starts_with("Cell<") ||
        type_name.starts_with("rusty::RefCell<") ||
        type_name.starts_with("RefCell<") ||
        // Also check for std::atomic which has interior mutability
        type_name.starts_with("std::atomic<") ||
        type_name.starts_with("atomic<")
    }
… which then 30 minutes later is being removed again because it turns out to be completely dead code: https://github.com/shuaimu/rusty-cpp/commit/84aae5eff72bb450...

There's also quite a lot of dead code. All of these warnings are around unused variable, functions, structs, fields:

    warning: `rusty-cpp` (bin "rusty-cpp-checker") generated 90 warnings (44 duplicates)

Can you show an actual minimal C program which has this problem? I’m trying to follow along here, but it’s very hard for me to understand the exact scenario you’re talking about.

Is there a specific reason to store the key + value as an `uint64_t` instead of just using a struct like this?

    struct slot {
      uint32_t key;
      uint32_t value;
    }

If a carpenter shows up to put a roof yet their hammer or nail-gun can't actually put in nails, who'd you blame; the tool, the toolmaker or the carpenter?

I would be unhappy with the carpenter, yes. But if the toolmaker was constantly over-promising (lying?), lobbying with governments, pushing their tools into the hands of carpenters, never taking responsibility, then I would also criticize the toolmaker. It’s also a toolmaker’s responsibility to be honest about what the tool should be used for.

I think it’s a bit too simplistic to say «AI is not the problem» with the current state of the industry.

I think this is a bit unfair. The carpenters are (1) living in world where there’s an extreme focus on delivering as quicklyas possible, (2) being presented with a tool which is promised by prominent figures to be amazing, and (3) the tool is given at a low cost due to being subsidized.

And yet, we’re not supposed to criticize the tool or its makers? Clearly there’s more problems in this world than «lazy carpenters»?

I’m sorry, but this is such a terribly unscientific approach. You want to make a case for your hypothesis? Follow a structured approach with real arguments.

Saying «I know that correlation doesn’t imply causation», but then only demonstrating correlation isn’t really bringing this discourse any further.

Ruby Blocks 9 months ago

Maybe I explained it a bit imprecise. I was trying to explain the following behavior:

    def foo
      p 1
      yield
      p 2
    end

    foo { break }
This only prints "1" because the break stops the execution of the invoked method (foo).
Ruby Blocks 9 months ago

Blocks are fundamentally different from functions due to the control flow: `return` inside a block will return the outer method, not the block. `break` stops the whole method that was invoked.

This adds some complexity in the language, but it means that it’s far more expressive. In Ruby you can with nothing but Array#each write idiomatic code which reads very similar to other traditional languages with loops and statements.

This has massive implications. SEC means low latency, because nodes don't need to coordinate to handle reads and writes. It means incredible fault tolerance - every single node in the system bar one could simultaneously crash, and reads and writes could still happen normally. And it means nodes still function properly if they're offline or split from the network for arbitrary time periods.

Well, this all depends on the definition of «function properly». Convergence ensures that everyone observed the same state, not that it’s a useful state. For instance, The Imploding Hashmap is a very easy CRDT to implement. The rule is that when there’s concurrent changes to the same key, the final value becomes null. This gives Strong Eventual Consistency, but isn’t really a very useful data structure. All the data would just disappear!

So yes, CRDT is a massively useful property which we should strive for, but it’s not going to magically solve all the end-user problems.

Suggest contrary to that is wrongthink and enough to have one ostracized not only from science, but also society as a whole.

There's many scientists who have published the "contrary". They were not ostracized from science or from society as a whole. These saw next to none negative impact to their position while they were alive. Other scientists have published rebuttals and later some of the originals articles have been retracted.

J. Philippe Rushton: 250 published articles, 6 books, the most famous university professor in Canada. Retractions of this work came 8 years after his death.

Arthur Jensen: Wrote a controversial paper in 1969. Ended up publishing 400 articles. Remained a professor for his full life.

Hans Eysenck: The most cited living psychologist in peer-reviewed scientific journal literature. It took more than 20 years before any of his papers were retracted.

There's a lot of published articles about the "contrary view" that you can read. You can also read the rebuttals by the current scientific consensus (cited above).

The analogous claim would therefore be that “although height differences have a large hereditary component, it does not follow that disparities in height between families have a genetic basis.” This seems very clearly false to me.

But this is not an analogous claim since you're talking about disparities between families. The analogous claim would be: "although height differences have a large hereditary component, it does not follow that disparities in height between groups have a genetic basis".

A very simple example for height[1]: The Japanese grew 10 cm taller from mid-20th century to early 2000s. Originally people thought that the shortness of the Japanese was related to their genetics, but this rapid growth (which also correlates with their improved economy) suggests that the group difference between Japanese and other groups was not related to the genetic component of height variance.

[1]: Secular Changes in Relative Height of Children in Japan, South Korea and Taiwan: Is “Genetics” the Key Determinant? https://biomedgrid.com/pdf/AJBSR.MS.ID.000857.pdf

Your first link (Wikipedia) directly contradicts your examples:

Although IQ differences between individuals have been shown to have a large hereditary component, it does not follow that disparities in IQ between groups have a genetic basis[18][19][20][21]. The scientific consensus is that genetics does not explain average differences in IQ test performance between racial groups.[22][23][24][25][26][27].

Traps to Developers 11 months ago

No, sorry. I was just remembering where I've typically seen sequential consistency being used. For instance, Peterson's algorithm was what I had in mind. Spinlock is indeed a good example (although a terrible algorithm which I hope you haven't seen used in practice) of a mutex algorithm which only requires acquire-release.

Traps to Developers 11 months ago

A mutex would be the most trivial example. I don't believe that is possible to implement, in the general case, with only acquire-release.

Sequential consistency mostly become relevant when you have more than two threads interacting with both reads and writes. However, if you only have single-consumer (i.e. only one thread reading) or single-producer (i.e. only one thread writing) then the acquire-release semantics ends up becoming sequential since the single-consumer/producer implicitly enforces a sequential ordering. I can potentially see some multi-producer multi-consumer queues lock-free queues needing sequential atomics.

I think it's rare to see atomics with sequential consistency in practice since you typically either choose (1) a mutex to simplify the code at the expense of locking or (2) acquire-release (or weaker) to minimize the synchronization.

Traps to Developers 11 months ago

Acquire-release ordering provides ordering guarantees for all memory operations. If an acquire observes a releases, the thread is also guaranteed to see all the previous writes done by the other thread - regardless of the atomicity of those writes. (There still can't be any other data races though.)

This volatile keyword appears to only consider that specific memory location whereas the Volatile class seem to implement acquire-release.

Jujutsu and Radicle 11 months ago

Here's a few workflows that I really enjoy in jj:

- While I'm working on something I can do `jj desc` and start writing the commit message. Every edit is automatically being added to this change.

- My work tree is dirty and I quickly want to switch to a clean slate. In Git: (1) either do `git stash` where I'm definitely is going to forget about it or (2) do `git commit -a -m wip && git switch -c some-random-branch-name`. In jj: `jj new @-`. That's it! If I run `jj log` then my previous change shows up. No need to come up with arbitrary names. It's so refreshing to move changes around.

- I'm working on a stack of changes and sometimes need to make edits to different parts. In Git (1): Each change is its own branch and I need to switch around and do a bunch of rebases to keep them in sync. In Git (2): I have one branch with multiple commits. I make changes towards the final state and then do `git rebase -i` to move them upwards to where they belong. Biggest downside: I'm not actually testing the changes at the point where they end up and I'm not guaranteed it makes sense. In jj: I do `jj new <CHANGE>` to make changes further up in the stack. Once I'm happy with it I do `jj squash` and every dependent change is automatically rebased on top.

- And finally: I can solve merge conflicts when I want to! If any rebasing leads to a merge conflict I don't have to deal with it right away.

This is one the reasons I find it so silly when people disregard Zig «because it’s just another memory unsafe language»: There’s plenty of innovation within Zig, especially related to comptime and metaprogramming. I really hope other languages are paying attention and steals some of these ideas.

«inline else» is also very powerful tool to easily abstract away code with no runtime cost.

Lock-free data structures does not guarantee higher throughput. They guarantee lower latency which often comes at the expense of the throughput. A typical approach for implementing a lock-free data structure is to allow one thread to "take over" the execution of another one by repeating parts of its work. It ensures progress of the system, even if one thread isn't being scheduled. This is mainly useful when you have CPUs competing for work running in parallel.

The performance of high-contention code is a really tricky to reason about and depends on a lot of factors. Just replacing a mutex with a lock-free data structure will not magically speed up your code. Eliminating the contention completely is typically much better in general.

With direnv you can also run commands directly in the .envrc:

    export OPENAPI_API_KEY=$(op read "op://api-prod/openai/api-key")
Every time you cd into the directory it will execute the command. Isn’t this even better than copying the secret into a local file?

The opposite of probabilistic is not deterministic in this context. This is not about «drawing a random number», but rather that balancing is dependent on the input data. «With high probability» here means «majority of the possible input data leads to a balanced structure».

If it was not probabilistic then the balancing would be guaranteed in all cases. This typically means that it somehow stores balancing information somewhere so that it can detect when something is unbalanced and repair it. In this data structure we’re just hashing the content without really caring about the current balance and then it turns out that for most inputs it will be fine.

… but it seems like the judge simply doesn't get the objections. And the reasoning is really strange

The full order is linked in the article: https://cdn.arstechnica.net/wp-content/uploads/2025/06/NYT-v.... If you read that it becomes more clear: The person who complained here filed a specific "motion to intervene" which has a strict set of requirements. These requirements were not met. IANAL, but it doesn't seem too strange to me here.

Also, rejecting something out of hand simply because a lawyer didn't draft it seems really antithetical to what a judge should be doing. There is no requirement for a lawyer to be utilized.

This is also mentioned in the order: An individual have the right to represent themselves, but a corporation does not. This was filed by a corporation initially. The judge did exactly what a judge what supposed to do: Interpret the law as written.

In most situations panicking and deferencing a null pointer leads to the exact same scenario: The binary crashes. You can unwind and catch panics in Rust, but I’m not sure if that would have helped in this scenario as it might have immediately went directly into the fault code again.

However, I would assume that the presence of an «unwrap» would have been caught in code review, whereas it’s much harder to be aware of which pointers can be null in Java/C++.

Here’s a quite recent interesting paper about this: https://dl.acm.org/doi/abs/10.1145/3643027

In this article, we study the convergence of datalog when it is interpreted over an arbitrary semiring. We consider an ordered semiring, define the semantics of a datalog program as a least fixpoint in this semiring, and study the number of steps required to reach that fixpoint, if ever. We identify algebraic properties of the semiring that correspond to certain convergence properties of datalog programs. Finally, we describe a class of ordered semirings on which one can use the semi-naïve evaluation algorithm on any datalog program.

It’s quite neat since this allows them to represent linear regression, gradient decent, shortest path (APSP) within a very similar framework as regular Datalog.

They have a whole section on the necessary condition for convergence (i.e. termination).

Boomph is a Rust re-implementation of BBHash which is included (and dominated by three other implementations). AFAIK there’s no reason to think it would perform any better than BBHash.