HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
mlochbaum
BQN
BQN2020–2026
mlochbaum / BQN

BQN

An APL-like programming language

12Distinct people
19Mentions
0Explicit recommenders
1.1KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

An APL-like programming language

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year19 dated mentions

Observed mentions: 2020-07-29 21:30:13 UTC to 2026-05-24 15:15:22 UTC.

012342020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 4 mentions; 2 submissions, 2 comments20202021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20232024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC422
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC211
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC202
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC202
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC404
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC202
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC303

What Hacker News says

19 sources
Ooh, I've run into this one before! I'm a big fan of interval index[0], which performs a binary search, so Josh's suggestion is the one I prefer as well (the implementation might sometimes optimize by transforming it into a table lookup like the other solutions). Searching for +`≠¨ in my BQN files turns up a few uses, including one used to group primitives into types in a utility involved in compiling BQN[1] and an annotated function used a few times in the markdown processor that builds BQN's website[2]. [0] https://aplwiki.com/wiki/Interval_Index [1] https://github.com/mlochbaum/BQN/blob/717555b0db/src/pr.bqn#... [2] https://github.com/mlochbaum/BQN/blob/717555b0db/md.bqn#L45-...
In Variation on Iota
Beyond what others have mentioned, I think another big differentiating factor between APL and the rest of those languages is that APL isn't focused on allowing the user to expand the language meaningfully, but rather on being a well-rounded language by itself (which is how it can be reasonably useful without objects with named fields, mutation, explicit loops (or only gotos in APLs infancy!), no first-class functions, no macros, and only one level of higher-order function (though of course most APL implementations have some of those anyway)). As such there's really no pretty "core" that pulls its weight to implement in 1000LoC and is useful for much. Here's a simple minimal APL parser in JS that I wrote once to display one way of parsing APL: https://gist.github.com/dzaima/5130955a1c2065aa1a94a4707b309... Couple that with an implementatio
Read the rest
n of whatever primitives you want, and a simple AST walker, and you've got a simple small APL interpreter. But those primitive implementations already take a good chunk of code, and adding variables/functions/nested functions/scoping/array formatting/etc adds more and more bits of independent code. Perhaps if you accept defining bits in the language in itself via a bootstrap step, BQN is a good candicate for existing small implementations - a BQN vm + minimal primitive set is ~500LoC of JS[0] (second half of the file is what you could call the native components of a stdlib), 2KLoC for first public commit of a C impl[1], both of those having the rest of the primitives being self-hosted[2], and the compiler (source text → bytecode) being self-hosted too[3]. (the C impl also used r0.bqn for even less required native primitives, but modern CBQN uses very little of even r1.bqn, having most important things native and heavily optimized) [0]: https://github.com/mlochbaum/BQN/blob/master/docs/bqn.js though earlier revisions might be more readable [1]: https://github.com/dzaima/CBQN/tree/bad822447f703a584fe7338d... [2]: https://github.com/mlochbaum/BQN/blob/master/src/r1.bqn (note that while this has syntax that looks like assigning to primitives, that's not actual BQN syntax and is transpiled away) [3]: https://github.com/mlochbaum/BQN/blob/master/src/c.bqn
In APL Interpreter – An implementation of APL, written in Haskell (2024)
The most uncompromisingly APL-ish code I've written is the BQN compiler[0]. Hard to write, hard to extend, hard to refactor. I generally recommend against writing this way in [1]. But... it's noticeably easy to debug. There's no control flow, I mean, with very few exceptions every line is just run once, in order. So when the output is wrong I skim the comments and/or work backwards through the code to find which variable was computed wrong, print stuff (possibly comparing to similar input without the bug) to see how it differs from expectations, and at that point can easily see how it got that way. The compiler's whole state is a bunch of integer vectors, and •Show [a,b,c] prints some equal-length vectors as rows of a table, so I usually use that. The relevant code is usually a few consecutive lines, and the code is composed of very basic
Read the rest
operations like boolean logic, reordering arrays with selection, prefix sum, and so on, so they're not hard to read if you're used to them. There are a few tricks, which almost all are repeated patterns (e.g. PN, "partitioned-none" is common enough to be defined as a function). And fortunately, the line prefaced with "Permutation to reverse each expression: more complicated than it looks" has never needed to be debugged. Basically, when you commit to writing in an array style (you don't have to! It might be impossible!) you're taking an extreme stance in favor of visible and manipulable data. It's more work up front to design the layout of this data and figure out how to process it in the way you want, but easier to see what's happening as a result. People (who don't know APL, mostly) say "write only" but I haven't experienced it. [0] https://github.com/mlochbaum/BQN/blob/master/src/c.bqn [1] https://mlochbaum.github.io/BQN/implementation/codfns.html#i...
In Arthur Whitney's one liner sudoku solver (2011)
There's not really that much specific to change I think; the general thing is just reducing the number of rules, as in a parallel thing you'll be applying every rule to every part versus just the rules given preceding context (there is the option of filtering parts to process if there are a bunch of rules applying to the same small subset of the input, but that requires such cont). All I can point at is from the array language world, with the notable thing of Co-dfns from Aaron Hsu, an APL compiler capable of running on the GPU (pointless as that may be): https://github.com/Co-dfns/Co-dfns/tree/master; and a 284-page dissertation: https://scholarworks.iu.edu/dspace/items/3ab772c9-92c9-4f59-... And Marshall Lochbaum following (https://mlochbaum.github.io/BQN/implementation/codfns.html) that work, and covering some basics of parsing express
Read the rest
ions of infix & prefix ops to stack-based/RPN at the bottom of https://mlochbaum.github.io/BQN/implementation/index.html, though the code is in BQN. From that same author, parsers written in BQN, that I think should have sub-linear critical paths: Markdown: https://github.com/mlochbaum/BQN/blob/master/md.bqn XML: https://github.com/mlochbaum/bqn-libs/blob/master/xml.bqn and a compiler of BQN itself: https://github.com/mlochbaum/BQN/blob/master/src/c.bqn (outputs stack-based bytecode).
In Scan HTML faster with SIMD instructions – Chrome edition
I don't put a lot of stock in the "write-only" accusation. I think it's mostly used by those who don't know APL because, first, it's clever, and second, they can't read the code. If I remember I implemented something in J 10 years ago, I will definitely dig out the code because that's the fastest way by far for me to re-learn how it works. This project specifically looks to be done in a flat array style similar to Co-dfns[0]. It's not a very common way to use APL. However, I've maintained an array-based compiler [1] for several years, and don't find that reading is a particular difficulty. Debugging is significantly easier than a scalar compiler, because the computation works on arrays drawn from the entire source code, and it's easy to inspect these and figure out what doesn't match expectations. I wrote most of [2] using a more traditio
Read the rest
nal compiler architecture and it's easier to write and extend but feels about the same for reading and small tweaks. See also my review [3] of the denser compiler and Co-dfns. As for being read by others, short snippets are definitely fine. Taking some from the last week or so in the APL Farm, {⍵÷⍨+/|-/¯9 ¯11+.○?2⍵2⍴0} and {(⍸⍣¯1+\⎕IO,⍺)⊂[⎕IO]⍵} seemed to be easily understood. Forum links at [4]; the APL Orchard is viewable without signup and tends to have a lot of code discussion. There are APL codebases with many programmers, but they tend to be very verbose with long names. Something like the YAML parser here with no comments and single-letter names would be hard to get into. I can recognize, say, that c⌿¨⍨←(∨⍀∧∨⍀U⊖)∘(~⊢∊LF⍪WS⍨)¨c trims leading and trailing whitespace from each string in a few seconds, but in other places there are a lot of magic numbers so I get the "what" but not the "why". Eh, as I look over it things are starting to make sense, could probably get through this in an hour or so. But a lot of APLers don't have experience with the patterns used here. [0] https://github.com/Co-dfns/Co-dfns [1] https://github.com/mlochbaum/BQN/blob/master/src/c.bqn [2] https://github.com/mlochbaum/Singeli/blob/master/singeli.bqn [3] https://mlochbaum.github.io/BQN/implementation/codfns.html [4] https://aplwiki.com/wiki/Chat_rooms_and_forums
In YAML Parser for Dyalog APL
I was able to get glidesort running as part of the Robin Hood sort benchmark[1]. See [0]; it's a lot slower than fluxsort on random data. Wondering if I did something wrong. Is cargo build --release with rustc 1.64.0 enough? Tried lto = "thin" in .cargo/config as well, which is ever so slightly faster. Also tried passing in a buffer one, then two, times the input length which didn't change things. Was this tested on x86? Commands to run to replicate my results are below. Clone rhsort and run them in that directory. The res/*.txt results are human-readable but you have to install my programming language[2] to generate the plot. Hey, you made me program in Rust. [0] https://gist.github.com/mlochbaum/7664a046d294dcce2f6cdb1db6... [1] https://github.com/mlochbaum/rhsort [2] https://github.com/mlochbaum/BQN ./wolfbench.sh mkdir res
Read the rest
gcc -O3 -D NOTEST bench.c && ./a.out l > res/r_rh.txt gcc -O3 -D FLUXSORT -D NOTEST bench.c && ./a.out l > res/r_flux.txt gcc -O3 -D WOLFSORT -D NOTEST bench.c && ./a.out l > res/r_wolf.txt g++ -w -fpermissive -O3 -D SKACOPY -D NOTEST bench.c && ./a.out l > res/r_ska_.txt cd glide && cargo build --release && cd .. gcc -O3 -D GLIDESORT -D NOTEST bench.c -Lglide/target/release -lglide LD_LIBRARY_PATH=glide/target/release ./a.out l > res/r_glide.txt images/line.bqn res/r_{flux,wolf,ska_,glide,rh}.txt > images/rand_glide.svg
In Show HN: Glidesort, a new stable sort in Rust up to ~4x faster for random data
Stories please! What did the closures do to you? Hopefully this won't be seen as too combative, but I feel like there are a few people in the array community giving me some pretty strong conclusions that they don't really have the experience to back up (Aaron wrote[0] 17 lines of array compiler, and says the low-abstraction approach he used is the only way to develop sustainably. Cool. I wrote[1] 350 lines of array compiler following his style, and I disagree[2]). At the same time, my experience only goes so far (there's no way I would have invented the array style compiler!), and clearly you arrived at these conclusions somehow. So is there a chance you'd share the observations that led you that way? On my end, I was actually introduced to a little object-oriented programming in J when Henry suggested using it for a simulation project. I
Read the rest
used it, but I don't think I really got it—just a weird way to organize data. And then in college I had to learn objects-only Java. Not good. But later I worked some with Node.js, and its module system was pretty nice: no name conflicts, easy to share code! Some way into BQN development, I figured out (with some help from a Common Lisp programmer) a way to add modules with an APL-y syntax, and something magic happened. I got objects[3] too! I think I've done about as much OOP in BQN as anywhere else, and I feel like I understand it a lot better now. So, this is my experience with Lisp-family features and APL. Fits like a glove, programming is easier and more fun. I mix and match array, functional, and object-oriented styles however I want. Did I lose coherence? When I translate my old J code it comes out shorter and cleaner and without exec (".) everywhere. But I still don't get why I should want the language I use to not support mutability rather than just default to immutability. Did I fail to understand something in J when I had the chance? [0] https://github.com/Co-dfns/Co-dfns [1] https://github.com/mlochbaum/BQN/blob/master/src/c.bqn [2] https://mlochbaum.github.io/BQN/implementation/codfns.html [3] https://mlochbaum.github.io/BQN/doc/oop.html
In Why APL is worth knowing
BQN! The entire BQN website is generated with a markdown processor[0] that handles the parts of Github-flavored markdown I use and adds features like highlighting and the ability to drop into BQN to generate html or svg. Github doesn't display markdown source nicely, but you can scroll down to the <!--GEN line in [1] to see how this diagram is made (plus definitions at [2]). [0] https://github.com/mlochbaum/BQN/blob/master/md.bqn [1] https://raw.githubusercontent.com/mlochbaum/BQN/master/comme... [2] https://github.com/mlochbaum/BQN/blob/master/svg.bqn
In What is a primitive?

Showing the 15 most recent of 19 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.