HNHacker News
TopNewBestAskShowJobs

xelxebar

3,028 karma · joined December 2, 2015

Contact info:

    Email local-part: boexahgahk
    Email domain: wilsonb.com
submissionscomments
xelxebar··on Everything is logarithms
The baseless log here is just a torsor [0]!

Lots of things are torsors: position, currency values, calendar dates etc. the vales themselves are arbitrary, and translating/scaling them by some value doesn't make a functional difference. Torsors let us talk about these things without needing to make such an arbitrary choice a priori.

In the case of baseless logs, the underlying set is "information units", i.e. log 2 is bits, log e is nats, log 10 is digits, etc. The conversion factors give us the torsor's group, and picking a privileged unit is just a trivialization of the torsor.

The vector division notation is, similarly, encoding a g-torsor in precisely the same way as length units are.

The examples so far are all torsors with abelian groups, but specifying position both requires choosing an origin and a length unit. The group of this torsor is a suitable semidirect product between translation and scaling, which gives a non-abelian group.

Most of the time we just implicitly choose a trivialization, which often causes confusion because it identifies objects with operations on them, e.g. conflating vectors as positions with vectors as translations. The author's treatise on problems with geometric algebra [1] even brings up this point!

[0]:https://math.ucr.edu/home/baez/torsors.html

[1]:https://alexkritchevsky.com/2024/02/28/geometric-algebra.htm...

xelxebar··on Report on an Unidentified Space Station – J.G. Ballard (1982)
This could possibly be hinting at a hyperbolic geometry. The game HyperRogue[0] gives of similar feels: you'll be walking through a cat invite land and spot a small dot on the horizon, only to discover that it's yet another vast infinite land. The game also kind of goes all in on the different tilings that a hyperbolic plane admits!

[0]:https://zenorogue.itch.io/hyperrogue

xelxebar··on What color is your function? (2015)
> I've spent the last decade in erlang / elixir / OTP.

Do you have a blog? I would love a peek into your unique experience.

xelxebar··on Mastering Dyalog APL
Eep. You're right. Evidently, I didn't even know what a sieve was in this context and wrote a search instead. You got me to do a bit of research. Actually, this discussion is exactly where I think APL shows one of it's strengths. It feels like a human communication tool more than any other PL I've mucked about with. The hard parts here are not language issues but fundamental understanding ones.

It's a tad tricky to carefully analyze the asymptotics of my above prime generator, since the search space of Without (~) shrinks on each iteration. I think Merten's theorem gives an estimate of e^-γ/log(p_i), which we need to sum for all primes up to N. Taking prime density 1/log(n) and integrating N/(log x)^2 over our range is O(N^2/log N), I think.

> Mutating a bit array in place is pretty important to classical sieve performance.

Challenge accepted:

    p⊣{x[⍵+n×⍳⌊N÷n←p⍪←x[⍵]]←0 ⋄ 1+⍣{(x⍪1)[⍵+1]≠0}⊢⍵}⍣{⍵=N-2}0⊣x p←(1↓1+⍳N)⍬
We just directly set roughly N/p items to 0 on each iteration—proper sieve semantics—which should give O(N log log N), unless I'm missing something.
xelxebar··on Mastering Dyalog APL
> At some point you get what APL is all about, and you can move on with life without too many regrets.

Unfortunately, this seems to be a common experience. A lot of smart people only engage with APL via toy puzzles, like you did, and bounce off because that gives no insight about how to use the language in real life. IME, to really start getting APL you need to write and rewrite a full application 20 times.

It helps to read code from the masters, too [0, 1, 2, 3, 4]. These all approach architecture in different ways: pedagogical FP style, OOP heavy, data-oriented design, event-driven state-machine, or a mix of the above.

[0]:https://dfns.dyalog.com/

[1]:https://github.com/Co-dfns/MicroUI-APL

[2]:https://github.com/Dyalog/ewc

[3]:https://github.com/Co-dfns/Co-dfns

[4]:https://github.com/Dyalog/Jarvis/blob/master/Source/Jarvis.d...

> As you can see, the famous prime generator is not even the Eratostenes' sieve, but a simple N^2 divisor counting computation.

Well, that's because you wrote a divisor function, not a seive. Arguably, the ease of typing an outer product (i.e ∘.|⍨⍳N) can tempt us into writing quadratic algorithms unnecessarily, but this is just an experience issue, IMO.

If we want a seive, we can just write one directly:

    p⊣{ω~n×1+⍳⌊N÷p⍪←n←ω↑⍨1⌊≢ω}⍣≡1↓1+⍳N⊣p←⍬
The algorithm is O(N log log N) as expected of a naive Eratosthenes implementation. You'll need ⎕IO←0 if you want to try it out.

There's also a faster seive by Roger Hui [0] in the dfns workspace as well as a family of prime number functions [1] for things more than just prime generation.

[0]:https://dfns.dyalog.com/n_sieve.htm

[1]:https://dfns.dyalog.com/n_pco.htm

xelxebar··on Thinking in an array language (2022)
> Pretty much write-only

I've written and worked on real-world APL applications, and this doesn't fit my experience. APL allows writing some of the most readable code out there, specifically because it makes whole-application architecture imminently more visible.

I like APL because it keeps me from bike-shedding on boilerplate or ceremony and forces me to consistently think about fundamental issues in the problem domain.

That said, APL by beginners (including myself, years ago) can be pretty terrible and effectively write-only. The steep learning curve is very real, and learning to write good APL is synonymous with learning good application architecture and UX.

xelxebar··on Thinking in an array language (2022)
> So if I understand this right K is one of the more popular/recommended APL-derivatives nowadays.

Only APL and K see real industry use. Both are actively developed. K is really a family of mutually incompatible languages, called K3, K4, K5, etc. Financial applications and most of the development is on K4, as far as I understand.

> Which APL derivatives (with an active/healthy userbase) besides k would you recommend to take a closer look at?

But why not APL? Dyalog has a team actively working on their interpreter, and industry has mostly converged around Dyalog APL now. If you want something well-worn through real-world use, then it's basically the only choice, unless you have money to drop on K4 or Shakti. Also, the literature is dominated by APL.

If you're more interested in array languages for their mathematical appeal and for tinkering on puzzle problems, then BQN will probably suit your tastes. If you don't like the symbols and want something open-source, then J is a strong option. If you wonder what kind of baby APL and Forth would have, then Uiua is just for you.

Note that while J and BQN can be considered APL variants, K is somewhat of a separate beast.

Have fun!

xelxebar··on Saying Goodbye to one line of APL
With an OR 2-scan, you can avoid the negation. Here's how I'd do it in APL: {⍵⌿⍨2∨⌿0⍪' '≠⍵}. In general, I find that boolean 2-scans pop up quite a bit in real-world APL usage. It's worth working through them. I have a short article [0] on the subject, if you're interested.

It's also worth thinking through how all 16 boolean operators work on boolean masks. E.g. what do msk≠msk2, msk<msk2, msk≤msk2 etc. mean? In my experience, the important part is to find crisp domain-specific meanings for these patterns. In general, really, that's how you gain APL fluency. In the same way that reading fluency requires chunking so that letters "disappear", APL fluency requires familiarity with semantic phrases, so you stop thinking in the individual symbols.

[0]:https://blog.wilsonb.com/posts/2023-07-24-suggestivity-and-i...

xelxebar··on Easy Random Trees
Maybe this should be another article, but there's a cool isomorphism between binary trees and forests of plane trees. Connects my article to the reason that you can count the number of ways to parenthesize n elements by C_n, the n-th Catalan number.
xelxebar··on Easy Random Trees
> I think the first sentence is very confusing...

Fair. You clearly engage with my article on a real level. More comments like yours will probably make my writing better. So, thanks!

That said, the code does precisely define s_i, which is s[i] in linearized notation. I scribbled the article together at 2am after a long day at work because a colleague asked for it and assume that you know APL or are at least willing try reading the code blocks.

> I think there's a much clearer way to prove this...

Honestly, I'm not a fan of arguments by contradiction when a clear constructive proof is available: The sequence of partial sums ends in 1; there is a rightmost partial sum that achieves the minimum partial sum, -N, say at index i. The remaining 1s and ¯1s, from index i+1 to the end, clearly must sum to N+1. Thus, left-rotating the sequence by i elements results in a strict ballot sequence. This is procedural and directly translates to the code.

xelxebar··on In Japan, the robot isn't coming for your job; it's filling the one nobody wants
> A quick google suggests ~18%

FWIW, this figure looks to be the fraction of 20–69 year olds in the entire population who are unemployed[0]. Referencing the official definitions[1], the standard unemployment figure of 2.6 (as of 2026-02) narrows that denominator to people who are receiving wages or actively looking for work.

> which naturally could be shifted by incentives like money or training.

From the above, 18% seems like the wrong number to look at. Heck, why not quote 38.1%, since it captures everyone who can legally work (including 15 and 90 year olds)?

IMO, the base population we want to look at is people who actually want a job, which is captured by various Labor Underutilization (LU) metrics. These all hover around 2.5–6.0% according to public records[2], and are also defined in the official docs[1].

[0]:https://www.stat.go.jp/data/roudou/sokuhou/tsuki/pdf/gaiyou....

[1]:https://www.stat.go.jp/data/roudou/pdf/hndbk5_2.pdf

[2]:file:///var/folders/96/k0p95wxn7sg5_xjnv5n233bc0000gn/T/gaiyou-1.pdf

xelxebar··on How far back in time can you understand English?
> Hit is muchel to seggen all þat pinunge hie on me uuroȝten, al þar sor and al þat sorȝe. Ne scal ic nefre hit forȝeten, naht uuhiles ic libbe!

My reading was "There is (too) much to say all that pain he wrought on me, all there sour and all that sorryness. Not shall I never forget, not while I live!"

xelxebar··on The largest number representable in 64 bits
Busy Beaver gets a lot of love, but the fast growing hierarchy is both constructive and can go way, way, waaaaay beyond current known BB bounds. This makes their size much more viscerally apparent than gesturing vaguely at BB(BB(BB(100))) or whatever, IMHO.

David Metzler has this really cool playlist "Ridiculously Huge Numbers" that digs into the details in an accessible way:

https://www.youtube.com/playlist?list=PL3A50BB9C34AB36B3

By the end, you're thinking about functions that grow so fast TREE is utterly insignificant. Surprisingly, getting there just needs a small bit of machinery beyond Peano Arithmetic [0].

Then you can ponder doing all that but making a tiny tweak by replacing succesorship with BB. Holy cow...

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

xelxebar··on 9front OS
The snapshot system in gefs is really quite nice.

By default, you get snapshots every minute for the last hour, every hour for the last day, and every day into perpetuity. This is configurable. You can set as many cadences as you wish, with the ability to configure their frequency and lifetimes.

Actually, snapshots are like btrfs volumes in many ways, meaning they can be mounted, read from, and written to as desired. This allows the filesystem root to just be another snapshot with a default backup cadence as described above.

The gefs(4) manpage [0] has more info for those interested. It's a short and sweet read. The source [1], is under 12k lines of well-written code, comments and whitespace included. The author is also extremely responsive to issues and a pleasure to talk shop with.

Anyway, given the parsimony of the OS and the small community size, I find 9front to be a really nice incubator for playing around with new ideas.

[0]:https://man.9front.org/4/gefs [1]:https://git.9front.org/plan9front/9front/front/sys/src/cmd/g...

xelxebar··on Are arrays functions?
IIRC, K rationalizes arrays and dictionaries with functions, e.g. you see arr[x;y] and fun[x;y]. Interestingly, this also highlights the connection between currying and projection, i.e. we can project/curry the above like arr[x] and fun[x].
xelxebar··on Ridiculously Huge Numbers [video]
Googol, googolplex, Graham's number, Ackermann's function, TREE, BB, Rayo's number ... For some reason big numbers seem to tickle some childlike fascination in me.

I randomly stumbled across this series that incrementally walks through the construction of truly gargantuan (computable) numbers. The fact that this touches on deep areas of math feels unexpected and fascinating.

Just wanted to share.

xelxebar··on Harvard legal scholars debate the state of the U.S. constitution (2025)
> This is by design. ... The federal government was never intended to lord over everyone's lives.

So behavior of the system fails to meet its design goals? It honestly sounds like you kind of agree with the excerpt you quote.

> The expansion of the federal government ... [is] what needs to change

What are you proposing though? Even assuming the premise here, achieving said goals requires changes to lots of little details and incentives. It's not like there's a single potentiometer controlling Gov't Size™. So what are you actually suggesting?

Certainly, the details of fundamental electoral structure engage deeply with the operation of our government, and the legal scholars in the article seem to be honestly pointing out levers (and big ones at that) we could possibly pull to create a less expansive federal government, or whatever the goal may be.

Imagine a plane crashes and analysts start attempting a root cause analysis, discussing control system specifics and whatnot. To me, your stance reads like "This is by design. Plane parts are united but independent. Control systems were never intended to lord over every part of the plane. The expansion of control systems is what needs to change."

I mean... maybe? But even if we agree on that point, any random contraction of the control system seems unlikely to make a plane that flies better. We have to actually engage with the details of what's going on here.

xelxebar··on What is Plan 9?
Thanks for the improvements! Two small quality of life fixes over the original that I particularly appreciate:

  - Window resize works as expected,
  - Doesn't lose input focus on resize or move, and
  - *Dyamic* scaling.
That last one has been really nice when screen sharing with colleagues.
xelxebar··on My Gripes with Prolog
Here's a nicely-designed tiling window manager, implemented in SWI-Prolog:

https://github.com/Seeker04/plwm

It actually has quite good UX affordances. More than that, however, I find the code imminently hackable, even as someone with very little Prolog experience. Reading through the plwm code really demystified the apparent gap between toy and practical Prolog for me. Heck, even the SWI-Prolog codbase itself is quite approachable!

I'm also mildly surprised at some of OG's gripes. A while back, I ran through Triska's The Power of Prolog[0], which crisply grounds Prolog's mental model and introduces standard conventions. In particular, it covers desugaring syntax into normal predicates, e.g. -/2 as pairs, [,]/2 as special syntax for ./2 cons cells, etc. Apparently, I just serendipitously stumbled into good pedagogical resources!

I'd be interested in ways that people utilize logical programming concepts and techniques into non-LP languages.

[0]:https://www.metalevel.at/prolog

xelxebar··on You need a kitchen slide rule
The Slide Rule Museum tickles hard some 2000's web nostalgia:

https://sliderulemuseum.com/

Last year I picked up a bamboo Hemi and worked through the (70yo!) workbook. The trigonometric scales are cool. Making a single slide to find all the sides of a triangle is surprisingly satisfying. It got me to realize that, sliderules with the right scales can solve the roots of any 3-variable equation. I guess this is why there was a proliferation of industry-specific sliderules back in the day.

More generally, aren't simple, well-engineered analog tools so satisfying?

xelxebar··on Text-based web browsers
One of my favorite pieces of software is edbrowse[0]. Perhaps surprisingly, I find it quite useful:

  - Main developer is blind, so accessibility has priority;
  - Easily scriptable; think automating captive portal clickthroughs;
  - Reading articles (e.g. Wikipedia) feels closer to reading a book;
  - It even supports JavaScript to a degree!
  - The affordances of line-oriented editing carry over nicely.
In particular, when using line-oriented interfaces, it's quite natural to build up a small collection of context-dependent snippets from documentation, source code, sample code, whatever. Putting a small collage of these on the screen is effortless and an experience I do miss with other UI paradigms.

The main developer appears to tinker on the project daily and is quite nice to chat with over on libera's #edbrowse. The project does have a small, dedicated following, but I wish more people knew about it!

[0]:https://github.com/edbrowse/edbrowse

xelxebar··on The PGP problem (2019)
Recently, this opinionated list of PGP alternatives went around:

https://soatok.blog/2024/11/15/what-to-use-instead-of-pgp/

One use case I've not seen covered is sending blobs asynchronously with forward secrecy. Wormhole requires synchronously communicating the password somehow, and Signal requires reasonable buy-in by the recipient.

Basically, I'd like to just email sensitive banking and customer data in an encrypted attachment without needing to trust that the recipient will never accidentally leak their encryption key.

xelxebar··on Nabokov's guide to foreigners learning Russian
> What do you mean Mandarin is simpler in this regard?

Just to add context to a sibling comment, Japan's first "writing system" was literally just Chinese.

I don't mean Chinese characters, I mean that if you wanted to write something down, you had to communicate in written Chinese. Over time this written Chinese accumulated more and more transformations bringing it in alignment with spoken Japanese until we get what we see today. However, this means that, to a first approximation, modern Japanese is some amalgamation of Old Chinese and Middle Japanese.

Actually, use of Chinese co-existed alongside the whole transformation process, so we actually see this funky mix of Early and Middle Japanese with Wu, Han, and Song Chinese. Character readings varied by region and time period, and so the the reading of a compound kanji term in Japanese mostly reflects the time period when that word was imported. This is why a single kanji ends up having multiple readings. Later, people began backporting individual characters onto native Japanese words, giving yet another reading.

The character 行 is a particularly illustrative example: 行脚 (an-gya), 行動 (kou-dou), 行事 (gyo-ji). The first reading "an" comes from 7th century Chinsese or so, "kou" comes a bit later from the Han dynasty, and "gyo" even later from Song. Then we have the backports: 行く末 (yu-ku-sue), 行く (i-ku), 行う (okona-u). The first "yu" reading is from Middle Japanese, "i" from Modern Japanese, and "okona" from I have no clue when. That's six different readings for 行 alone!

Oh, and then there are "poetic" readings that are specific to usage in people's names: 弘行 (hiro-yuki) etc. Granted, these are often quite evocative of the above readings or that of synonym characters.

The historical introduction process also explains why older readings tend to be more obscure, 1) they had less time to accumulate usage, and 2) they tend to be specific to Buddhist and administrative themes.

Note: The above is just what I've pieced together osmotically over the years, so I'm sure there are errors.

xelxebar··on An attempt to articulate Forth's practical strengths and eternal usefulness
Oh, cool! SmithForth[0] is how I originally learned about x86-64 microarchitecture. It's a Forth that bootstraps off hand-coded x86-64 opcodes. I decided to go the other direction and decompile the binary by hand. It really is a beautiful piece of code. Highly recommended reading.

Also, you're excited by Forth and Lisp, you might like Forsp[1]. It uses a call-by-push-value evaluation strategy in a way that really makes the language feel like a true hybrid of the two. The implementation is also brilliantly simple.

Anyway, thank you for the article. I lurk on the DuskOS mailing list and wish I could find out where the Forthers gather IRL so I could osmote more of their world into my own.

[0]:https://dacvs.neocities.org/SF/

[1]:https://xorvoid.com/forsp.html

xelxebar··on An Implementation of J (1992)
> I'm not entirely convinced it actually helped me as a "tool of thought"

This is so real. I had the same issue and was only able to break through by collabing with professional APLers. It's very non-ideal for the curious autodidacts.

I'd love to share, hone, and flesh out what the Tool of Thought looks like in practice with interested others. For anyone here to whom that sounds fun, feel free to reach out. Contact info is in my profile.

xelxebar··on Array-programming the Mandelbrot set
My YAML loader[0] is a condensed example of the architecture and techniques I'm thinking of. It's a couple years old, so the code is dirty by my current standards, but the couple of times I've gone back to read it, I have found the YAML-specific concerns to be quite salient.

That said, it's specifically written for an audience that is familiar with YAML detail in particular, parsing more generally, and of course APL expressions of ideas. In fact, that is a big part of what makes the code readable and maintainable: it is optimized for communicating to the expert worker not for on-boarding new developers. The latter is more appropriately handled via other means IMHO.

The poster child for this style of APL is Co-dfns[0]. It's a production APL compiler and a much larger example of the code I'm talking about. The entrypoint to read is cmp/PS.apl.

If you're interested, I'm willing to have a chat and talk more about what makes this kind of APL imminently workable, in which case there are also some personal private examples I could share as well. Feel free to reach out to the contact info on my profile here.

[0]:https://github.com/xelxebar/dayaml/blob/master/Y.apln.

[1]:https://github.com/Co-dfns/Co-dfns

xelxebar··on Array-programming the Mandelbrot set
The author is clearly a novice who has just tinkered with array languages a little. Extrapolating from that to absolute properties of a tool seem a bit overeager, don't you think? For example, do you think you could design a legible analog circuit without significant time learning the craft?

My experience is with APL, but I think it is capable of producing some of the most readable and maintainable codebases out there. I've worked for years in various projects using Python, Java, C, Scheme, and a smattering of many other languages. However, it's really hard to overstate the clarity that comes from data-oriented design and dogged elimination of API boundaries.

It just takes a long time to learn to write good software in good APL style. In many ways all the in vogue best practices these days around declarative and functional programming tend to work antithetically to writing good array code. This means that the learning curve for experienced programmers is, perhaps paradoxically, higher than that of a totally naive beginning coder.

I really wish I knew some way to directly convey the experience of working with APL at a high level. There's really nothing else much like it.

xelxebar··on Learning to read Arthur Whitney's C to become smart (2024)
> The way to understand Arthur Whitney's C code is to first learn APL

This is the main insight in my breakdown of the J Incunabulum:

https://blog.wilsonb.com/posts/2025-06-06-readable-code-is-u...

When I first encountered it years ago, the thing was impenetrable, but after learning APL to a high level, it now reads like a simple, direct expression of intent. The code even clearly communicates design tradeoffs and the intended focus of experimentation. Or more on the nose, to me the code ends up feeling primarily like extremely readable communication of ideas between like-minded humans. This is a very rare thing in software development in my experience.

IMHO, ideas around "readable code" and "good practices" in software development these days optimize for large, high-turnover teams working on large codebases. Statistically speaking, network effects mean that these are the codebasese and developer experiences we are most likely to hear about. However, as an industry, I think we are relatively blind to alternatives. We don't have sufficient shared language and cognitive tooling to understand how to optimize software dev for small, expert teams.

xelxebar··on Bcachefs Goes to "Externally Maintained"
I've used btrfs for 5-ish years in the most mundane, default setup possible. However, in that time, I've had three instances of corruption across three different drives, all resulting in complete loss of the filesystem. Two of these were simply due to hard power failures, and another due to a flaky cpu.

AFAIU, btrfs effectively absolves itself of responsibility in these cases, claiming the issue is buggy drive firmware.

xelxebar··on My phone is an ereader now
You might be interested in this:

https://www.crowdsupply.com/modos-tech/modos-paper-monitor

It's just a dev kit run, but I've got high hopes for the whole Modos project.

← PreviousPage 3 of 32Next →