[HN Gopher] APL Interpreter - An implementation of APL, written ...
       ___________________________________________________________________
        
       APL Interpreter - An implementation of APL, written in Haskell
       (2024)
        
       Author : ofalkaed
       Score  : 130 points
       Date   : 2025-06-05 21:22 UTC (1 days ago)
        
 (HTM) web link (scharenbroch.dev)
 (TXT) w3m dump (scharenbroch.dev)
        
       | behnamoh wrote:
       | Depending on your personality type (perfectionist or pragmatic),
       | this is either the best of both worlds or the worst.
        
       | valcron1000 wrote:
       | My favorite language used to interpret my most hated language
       | (used both professionally).
       | 
       | There are several things I disagree with regarding Haskell but
       | it's understandable given that this is OP's first time using the
       | language (like a "monad's internal state"), but I want to
       | highlight one particular observation:
       | 
       | > This uncertainty of time of evaluation also makes catching
       | errors difficult, because calling catch on the function that
       | throws the error will not necessarily catch that error
       | 
       | It's important to distinguish between imprecise exceptions (ex.
       | calls to `error `, `undefined`, and the like) and synchronous
       | exceptions (async exceptions are not important for the article).
       | 
       | > Catch must be called on the function that forces evaluation on
       | that error. This is something that is hard to trace, and
       | something that types don't help much with.
       | 
       | The types are actually the most important part here! Synchronous
       | exceptions cannot be thrown by pure code (as long as we're not
       | dealing with escape hatches like `unsafePerformIO`), while IO
       | code can throw and catch all kind of exceptions .
        
         | tome wrote:
         | Regarding catch, yes, I agree types help, but they can help
         | even more! I suggest an IO-wrapper effect system (mine is
         | called Bluefin; effectful is also a good choice). Then there is
         | absolutely no ambiguity about where an exception can be
         | handled. There is exactly one place -- no more, no less. It
         | makes dealing with exceptions very easy.
         | 
         | https://hackage.haskell.org/package/bluefin-0.0.16.0/docs/Bl...
        
       | instig007 wrote:
       | > Apparently Haskell's performance isn't that bad, but I don't
       | plan on using Haskell for anything that is remotely performance-
       | sensitive. Trying to optimize Haskell code does sound like an
       | interesting problem, but it might be a lost cause.
       | 
       | When the dude uses `foldl` over lists and `foldr` with `(*)`
       | (numeric product) it is not the language that's the lost cause.
        
         | kccqzy wrote:
         | In case anyone who doesn't know Haskell: both of these are
         | beginner level mistakes. Using `foldl` causes space leaks and
         | turns your O(1) space algorithm to O(N) space for no good
         | reason. And using `foldr` over lists is good when you are
         | dealing with unevaluated lists and want list fusion, but not
         | when they already exist in memory and will continue to do so.
         | And that doesn't even include the obviously wrong choice of
         | data structure, built-in Haskell lists are singly-linked lists
         | not arrays. There are Array types and Vector types (both come
         | with GHC so no extra dependency needed) that are more
         | appropriate for implementing APL in the first place.
        
           | itishappy wrote:
           | > And using `foldr` over lists is good when you are dealing
           | with unevaluated lists and want list fusion, but not when
           | they already exist in memory and will continue to do so.
           | 
           | What's the preffered approach?
        
             | farrellm23 wrote:
             | Usually you want `foldl'` (with ' at the end), the strict
             | version of `foldl`. It prevents the creation of
             | intermediate thunks, so effectively a tail recursive
             | iteration over the list in constant space.
             | 
             | `foldr` I almost never use, but it would be for: the return
             | value is a lazy list and I will only need to evaluate a
             | prefix.
        
               | zoul wrote:
               | The naming conventions are nicely sadistic.
        
               | WorldMaker wrote:
               | This is what happens when you let Mathematicians name
               | things on chalkboards. They don't want to run out of
               | chalk and they get tired of spelling whole words very
               | easily so they use short names and silly symbols. The
               | name foldl' is "just" "fold left prime". Remember ' means
               | "prime" from calculus class and thinking that was silly
               | even then? Accidentally infected Haskell at a young age.
        
               | Rendello wrote:
               | > This is what happens when you let Mathematicians name
               | things on chalkboards.
               | 
               | Doubly so with APL!
        
               | kccqzy wrote:
               | Yeah it's definitely unusual to allow ' to be part of the
               | name of a variable, especially considering that it is,
               | like C, the quote for character types.
        
             | tome wrote:
             | I have the definitive answer to this question in my article
             | "foldl traverses with State, foldr traverses with anything"
             | 
             | https://h2.jaguarpaw.co.uk/posts/foldl-traverses-state-
             | foldr...
             | 
             | In short: use foldl' when you're iterating through a list
             | with state. foldr can be used for anything else, but I
             | recommend it for experts only. For non-experts I expect
             | it's easier to use for_. For more details about that see my
             | article "Scrap your iteration combinators".
             | 
             | https://h2.jaguarpaw.co.uk/posts/scrap-your-iteration-
             | combin...
        
               | kccqzy wrote:
               | Is it really easier to use for_? It forces you to think
               | about effects rather than pure data. So you end up
               | packaging data into effects through State or similar
               | monads. So is it really easier if you force people to use
               | Monad (well technically Applicative)?
        
         | pierrebeaucamp wrote:
         | > When the dude uses `foldl` over lists and `foldr` with `(*)`
         | (numeric product) it is not the language that's the lost cause.
         | 
         | This is a great example of Haskell's community being toxic. The
         | author clearly mentioned they're new to the language, so
         | calling them a "lost cause" for making a beginner mistake is
         | elitist snobbery.
         | 
         | I usually don't point these things out and just move on with my
         | life, but I went to a Haskell conference last year and was
         | surprised that many Haskell proponents are not aware of the
         | effects of this attitude towards newcomers.
        
           | instig007 wrote:
           | > calling them a "lost cause" for making a beginner mistake
           | is elitist snobbery.
           | 
           | I wonder how do you call the practice of complete beginners
           | spreading FUD and suggesting to their readers that something
           | in the language is "a lost cause", all whilst having neither
           | enough knoweldge nor sufficient practice to make assumptions
           | of this kind.
           | 
           | > This is a great example of Haskell's community being toxic
           | 
           | To be clear: I don't represent haskell community, I'm not
           | part of it, and I couldn't care less about it. It just so
           | happened that I saw the author inflating their credentials at
           | the expense of the language via spreading FUD, that the
           | beginners you seem to care about are susceptible to, and I
           | didn't like it.
           | 
           | If you get triggered by the expressed dissatisfaction with
           | the author's unsubstantiated presumptuousness, reflected back
           | at them in a style and manner they allowed themselves to talk
           | about the thing they don't know about, then it's purely on
           | you and your infantilism.
        
           | tome wrote:
           | Can I ask which conference? Did people behave towards you in
           | that way at that conference, or are you referring to
           | behaviour online? I will try to use whatever authority I have
           | in the Haskell community to improve the situation.
           | 
           | (Still, hopefully in this case it's clear from instig007's
           | reply that it's not a member of the Haskell community
           | behaving in that way.)
        
             | pierrebeaucamp wrote:
             | This is almost exclusively just online behaviour. Everyone
             | I met in person is very nice :).
             | 
             | The conference I mentioned was ZuriHac. After the key-note
             | Q&A there was a small hallway discussion around how to grow
             | the adoption / reach of Haskell. The conversation revolved
             | around mostly technical points (like how Haskell is
             | superior to x, because of y). What I found interesting was
             | that there was little to no talk about the steep learning
             | curve, developer ergonomics or business use-cases.
             | 
             | The thing is, if someone has not yet learned about
             | functional programming, strong type systems or category
             | theory, why / how would they see the advantages or the
             | power of pure functions, lazy evaluation, Monads, etc. At
             | the same time, their opinions or struggles are often
             | dismissed due to their lack of knowledge. The parent
             | comment is a prime example of this.
             | 
             | Edit: This is a great 10-minute talk that touches on the
             | general topic: https://www.hytradboi.com/2025/419859c5-6a8f
             | -4a49-b324-0f225... She covers a lot of this better than I
             | can.
        
           | kccqzy wrote:
           | Newcomers need the self-awareness to understand that they are
           | newcomers and that their opinions are more often than not
           | wrong. This author doesn't have that humility.
           | 
           | It is simply aggravating to see newcomers without humility
           | speak with an authoritative tone on subjects they barely
           | know.
        
       | howerj wrote:
       | Is there an implementation of an APL language (or other any other
       | array language) written in * _readable*_ C that is around 1000
       | LoC? There are for LISP, FORTH, Prolog, TCL and the like.
        
         | ofalkaed wrote:
         | Not that I have found, closest is an incomplete one done in
         | python.
         | 
         | https://mathspp.com/blog/tag:lsbasi-apl#body-wrapper
        
         | itishappy wrote:
         | What, you don't like Arthur's style?
         | 
         | https://www.jsoftware.com/ioj/iojATW.htm
         | 
         | https://github.com/kparc/ksimple/blob/main/ref/a.c
         | 
         | Slightly less factiously, the ksimple repository has a version
         | with comments.
         | 
         | https://github.com/kparc/ksimple
         | 
         | https://github.com/kparc/ksimple/blob/main/a.c
         | 
         | Note, these aren't APL, but they are in the same family of
         | array languages.
        
         | xelxebar wrote:
         | Unlikely, at least for what I think you mean by "readable"
         | here.
         | 
         | APL isn't really one of these exhibitions of computational
         | simplicity in the way of the languages you mention. It's
         | inventor, Kenneth Iverson, was more focused on the human side
         | of thinking in and using the language.
         | 
         | Forth, Lisp, _et al_ are quite easy to implement, but they
         | require considerable library layers on top to make them useful
         | for expressing application-level logic, even if we just focus
         | on the pure functions. APL, on the other hand, has a larger
         | core set of primitives, but you 're then immediately able to
         | concisely express high-level application logic.
         | 
         | Are you looking for a kind of reference implementation for
         | learning purposes? If so, I'd say the best route is just go
         | with the docs. Arguably the Co-dfns compiler is a precise spec,
         | but it's notably alien to non-practitioners.
        
           | ofalkaed wrote:
           | Any pointers on how to get better at expressing high-level
           | application logic in APL? Any good resources on programming
           | in APL? So far I have only found tutorials and basic stuff
           | for learning APL but not much on applying APL. I am slowly
           | improving and think I sort of get it but probably don't.
        
             | xelxebar wrote:
             | Not that I know of, unfortunately. This is, IMHO, the
             | biggest pain point of APL pedagogy at the moment. I'm
             | actually working on some resources, but they're still
             | gestating.
             | 
             | For non-event driven systems, the short story is to
             | organize application state as a global database of inverted
             | tables and progressively normalize them such that short APL
             | expressions carry the domain semantics you want.
             | 
             | For event driven systems, we have token enumeration over
             | state machines, which can be expressed as literal Branches
             | to state blocks.
             | 
             | Granted, the above likely doesn't communicate well unless
             | you're already primed with all the necessary ideas. If
             | you're interested, I'm willing to chat. Email is in my
             | profile description.
             | 
             | source: Current day-to-day is greenfield APL dev.
        
               | ofalkaed wrote:
               | >IMHO, the biggest pain point of APL pedagogy at the
               | moment
               | 
               | It is the one that always trips me up. I just started in
               | on my third attempt at learning APL/array languages, both
               | previous times I got to the same point where I was mostly
               | at a loss of how to apply it all. So I move on and forget
               | all that I learned until the next time and have to start
               | over. Thankfully the last attempt seems to have mostly
               | stuck as far as keyboard layout goes, makes progress much
               | quicker.
               | 
               | I may take you up on that email offer once I get a bit
               | further along in this current attempt, can't quite form
               | reasonable questions yet and only know what tripped me up
               | in the previous attempts. I believe you are a regular on
               | APL Orchard? I will be joining it soon so perhaps will
               | see you there.
        
               | xelxebar wrote:
               | Yes, I'm one of the few regularly in the Orchard. There's
               | also the APL Farm discord, which is chattier.
               | 
               | In the off chance you've not see this:
               | https://aplwiki.com/wiki/Chat_rooms_and_forums
        
             | geocar wrote:
             | What would you consider "high-level application logic"?
        
               | ofalkaed wrote:
               | The logic of the system instead of the pieces of the
               | system; how the language's core data structure
               | applies/relates towards expressing that system. I could
               | very well be overthinking things and seeing some sort of
               | magic which is not there but this line in the previous
               | response to me, makes me think I am still missing a piece
               | of the puzzle:
               | 
               | >organize application state as a global database of
               | inverted tables and progressively normalize them such
               | that short APL expressions carry the domain semantics you
               | want.
        
               | gitonthescene wrote:
               | I may be reading too much into this but it sounds like
               | you're searching for templates to stimulate ideas similar
               | to how there are examples for smaller puzzle type
               | problems.
               | 
               | I think most sizable stuff is proprietary. I implemented
               | an lsp in an open source K which uses json/rpc. But the
               | open source K is probably best considered a hobby
               | project.
               | 
               | https://github.com/gitonthescene/ngnk-
               | lsp/blob/kpath/k/lsp.k
               | 
               | You might consider joining one of the APL forums if you
               | haven't already.
        
               | geocar wrote:
               | Ok. I have some idea I think of where you are at, so I
               | will give it a shot. I think this sort of thing is an
               | emergent property in the design of APL applications, and
               | so there's nothing to "see" in terms of an example unless
               | you can see that design process.
               | 
               | But first, "database" here is just the list of global
               | variables. If that wasn't obvious, it is important.
               | 
               |  _My_ application processes weblogs, and  "clicks" is the
               | bit-array of which event was a click (redirect), as
               | opposed to having a variable called "weblog" which
               | contains a list of records each possibly having an event-
               | type field.
               | 
               | Normalizing them that acknowledges that the weblog
               | (input) probably looked like the latter, but it's easier
               | to do work on the former. APL makes that transformation
               | very easy: Just rotate the table. In k this is flip.
               | Simples.
               | 
               | Those "domain semantics" are simply the thing I want to
               | do with "clicks" which in my application comes from the
               | business (users), so I want them to provide a bunch of
               | rules to do that.
               | 
               | Now with that in mind, take a look here:
               | 
               | https://code.jsoftware.com/wiki/Vocabulary/bdot#bitwise
               | 
               | and here:
               | 
               | http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperS
               | pec...
               | 
               | Look _carefully_ at the tables, because they 're given in
               | a slightly different way, but they are the same. And
               | these are all of them, so it should be obvious at this
               | point you can represent any boolean operation against any
               | matrix of variables with a matrix of these numbers.
               | 
               | For example, you might have a sql-like expression (from a
               | user of your application) of x=y, and x<y and so on that
               | you want to use to filter some data set.
               | 
               | Now if you are to think about how you might do this in
               | Javascript (for example; probably in scheme too) you
               | would probably organise such a table as a chain of
               | closures. And I think if you look at any ORM in just
               | about any language you'll see this kind of pattern (maybe
               | they use classes or use a tree, but these are obviously
               | the same as closures), but such a tree can _only_ be
               | traversed, and the closure can _only_ be called. Maybe
               | you can batch or shard, but that 's it, and since I would
               | bet there are a lot of dependant loads/branching in this
               | tree of closures, it is slow.
               | 
               | But if you understand that this tree is also a matrix of
               | boolean operators, it is obviously parallelisable. And
               | each operation is simple/cache-friendly and so therefore
               | fast. This leads to your "queries" being a set of
               | projected indexes or bitmaps (whichever is convenient),
               | which you probably also store in global variables
               | someplace (because _that_ is convenient) while you 're
               | doing what you need to do (make xml, json, bar charts,
               | run programs, whatever)
        
         | geocar wrote:
         | ngn's k is publicly available, around 1000 lines and readable,
         | in that I can read it.
        
         | gitonthescene wrote:
         | Readable is probably in the eye of the beholder but here's a
         | partially expanded version of ngn/k
         | https://codeberg.org/growler/k/src/branch/expand/a.c
         | 
         | The expansion is mechanical and thus not really at attempt at
         | readability.
        
         | dzaima wrote:
         | 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 implementation 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
        
       | nickzelei wrote:
       | Interesting read!
       | 
       | On a semi-related topic: I tried learning Haskell this past
       | weekend out of curiosity that I last tried it some 10+ years ago
       | while still in college.
       | 
       | I found resources for it scant. Coming from more modern
       | languages/tooling like Go/Rust, I also struggled quite a bit with
       | installation and the build/package system.
       | 
       | I tried the stack template generator for yesod/sqlite and after
       | some 15 minutes of it installing yet another GHC version and
       | building, I eventually ctrl+C'd and closed out of the window.
       | 
       | Maybe this was a unique experience, but I'd love some guidance on
       | how to be successful with Haskell. I've primarily spent most of
       | my professional years building web services, so that was the
       | first place I went to. However, I was taken aback by how
       | seemingly awful the setup and devex was for me. I've always been
       | interested in functional programming, and was looking to sink my
       | teeth in to a language where there is no other option.
        
         | itishappy wrote:
         | My understanding is that Cabal has more or less supplanted
         | Stack. Use GHCup to install everything, then use `cabal init`,
         | `cabal run`, or `cabal repl` like you would in Go/Rust.
         | 
         | Stack builds on top of Cabal, and used to solve a bunch of
         | problems, but the reasons for it's existence are no longer
         | super relevant. It still works totally fine if that's your
         | thing though.
        
           | nickzelei wrote:
           | That is so interesting and is a point where GPT has failed me
           | if this is true. My understanding was the stack was the
           | choice due to having better ergonomics over cabal. Apparently
           | that isn't true? I Found that stack init was pretty decent at
           | setting up a project structure, but can't say I tried cabal
           | init.
           | 
           | I initially installed ghcup via homebrew but found that did
           | not set things up correctly and had to follow the install
           | from their site, which made things work more smoothly.
        
         | shae wrote:
         | The easiest and fastest way to get everything installed is
         | ghcup https://www.haskell.org/ghcup/
         | 
         | As for being successful, there are several nice books, and
         | several active forums. I've gotten good answers on the Libera
         | IRC network #haskell channel, and on the Haskell matrix channel
         | #haskell:matrix.org
         | 
         | If you want to get started without installing anything, there's
         | the exercism track: https://exercism.org/tracks/haskell
         | 
         | I've heard good things about Brent Yorgey's Haskell course (
         | https://www.cis.upenn.edu/~cis1940/spring13/lectures.html ) but
         | haven't tried it myself.
        
           | nickzelei wrote:
           | Appreciate the resources!
        
         | cosmic_quanta wrote:
         | I learned using the Haskell Programming from First Principles
         | book (haskellbook.com). I don't think it goes into web
         | development, but it certainly goes through the basic project
         | setup.
         | 
         | Do you think you would have benefitted from a resource like the
         | Rust book? I've been toying with the idea of writing something
         | similar and donating it to the Haskell Foundation
        
           | nickzelei wrote:
           | I've seen this book referenced a few times and is quite large
           | from what I've seen.
           | 
           | Not opposed to checking it out, but to your question: I
           | really like the Rust book and how easy it is to find and
           | read. It feels modern, up to date, and the standard for how
           | to learn Rust.
        
         | internet_points wrote:
         | https://typeclasses.com/phrasebook is a good resource
        
           | nickzelei wrote:
           | This is great! I like the note at the bottom of the page that
           | it is inspired by Go/Rust by example.
           | 
           | After checking it out this is definitely on the way to what
           | I"m looking for. Direct, no-nonsense examples that are easy
           | to find and grok.
        
         | WorldMaker wrote:
         | I loved the book "Real World Haskell" [1] when it first came
         | out in 2008. It feels like a shame it hasn't aged well and
         | there hasn't been an updated edition since then. Especially
         | because it was focused on things like "here's how you build
         | example web services" as a good place to discuss everything
         | else by having the end goal of the book's "narrative" structure
         | be real world things you might build. It may still help to
         | glance at a little, but things have advanced so much in the
         | decade and a half since the book was written it is hard to
         | recommend, but it still feels like there should be a book like
         | it updated for current day to be out there to more heartily
         | recommend. If there is one I don't know of it, but I haven't
         | followed Haskell as much as I'd like in my professional career.
         | 
         | [1] https://book.realworldhaskell.org/
        
       | 0xTJ wrote:
       | Seeing "all built-in functions and operators are single unicode
       | symbols" stood out to me, given that APL existed well before
       | Unicode did. It's not that it's wrong today, but that wasn't
       | always the case. My father used APL back in high school, and that
       | was before the earliest year mentioned in the "History" section
       | of the Unicode Wikipedia article.
        
         | gitonthescene wrote:
         | It wasn't Unicode but it wasn't ASCII either. I think here
         | unicode is probably shorthand for not ASCII.
        
           | WorldMaker wrote:
           | Unicode inherited most of APL's encoding sets from EBCDIC
           | code pages. Almost no one would _choose_ to work in EBCDIC
           | today, so it is practical to just say Unicode as the last
           | encoding left standing (for everyone not working on legacy
           | APL code on [emulated] IBM mainframe hardware).
        
       | xelxebar wrote:
       | > Array programming is similar to functional programming - the
       | primary way to control execution involves composition of
       | functions - but APL tends to encourage the reliance on global
       | properties and sweeping operations rather than low-level
       | recursion4.
       | 
       | This AoC solution is, indeed, quite the functionista! Better yet,
       | it leans heavily into point-free expressions. The style is pretty
       | popular amongst APL language enthusiasts and puzzlers.
       | 
       | That said, you actually see quite different APL styles in the
       | wild:
       | 
       | - Pointed declarative style, also a popular with functional
       | programmers (e.g. anything like this[0] from the dfns workspace)
       | 
       | - Imperative, structured programming, very common in legacy
       | production systems (e.g. this[1] OpenAI API interface)
       | 
       | - Object-oriented, also common in somewhat newer production
       | environments (e.g. the HTTP interface[2])
       | 
       | - Data-parallel style (e.g. Co-dfns[3])
       | 
       | Heck, APL even has lexical and dynamic scope coexisting together.
       | IMHO, it's truly underrated as a language innovator.
       | 
       | [0]:https://dfns.dyalog.com/c_match.htm
       | 
       | [1]:https://github.com/Dyalog/OpenAI/blob/main/source/OpenAI.apl.
       | ..
       | 
       | [2]:https://github.com/Dyalog/HttpCommand/blob/master/source/Htt.
       | ..
       | 
       | [3]:https://github.com/Co-dfns/Co-dfns/blob/master/cmp/PS.apl
        
       | librasteve wrote:
       | this is pretty cool
       | 
       | i think the first raku (perl6) parser (pugs) was written in
       | Haskell, certainly all the team learned Haskell before they
       | started
        
         | _glass wrote:
         | Done by Audrey Tang who later on became Minister of Digital
         | Affairs of Taiwan.
        
       ___________________________________________________________________
       (page generated 2025-06-06 23:01 UTC)