User:⊂⍺m

From APL Wiki
Jump to navigation Jump to search

Background

Novice hobbyist programmer. Have been learning APL and J immersively for several months and have been enjoying the whole process. This wiki has been a great help!

APL and J are the first languages I’ve really immersed myself in. Prior to these, I’ve just coded a bit of C and Java in college, and a bit of Haskell and Racket Scheme on my own. I stumbled upon Haskell as a way to augment the solving of college physics problems, and this was my introduction to “sane”, elegant, straightforward computing—no “public static void main,” no boilerplate, no syntax, just the functions, annotated by type. Using Haskell made the course infinitely more fun, and made solving homework infinitely more efficient, as it freed me from the tedium of needing to carefully and meticulously enter everything into the calculator properly, round the significant figures properly, etc. Now, if I got the wrong answer, I could be assured that the issue was the result of a conceptual misunderstanding, and not from some trivial mistake with using the calculator (which had happened very frequently!).

Encountering APL and J

I first encountered APL on the Rosetta Code site, which showcases solutions to given toy problems in virtually every language out there. Not only were the characters visually enticing, but of course virtually every APL solution was given in half a line of code, whereas virtually all other languages’ solutions took up anywhere from a dozen to a few dozen lines. J, K, and Joy/Factor were also among these astounding terse (“expressively efficient,” in my mind) languages. J seemed especially fascinating since all its solutions were given in tacit code—even recursive solutions like quicksort! So, I read about APL and Iverson’s “notation as a tool of thought” concept, and wanted nothing more than to master APL and J.

Learning APL and J

The task of learning APL and J is a bit tricky since all the code examples for the primitive you’re studying are written in terms of other unfamiliar primitives. As J’s NuVoc pages are among the most informative and well-organized, I largely relied on those, although I wanted to learn APL before J. So I basically ended up learning J and APL at the same time, which isn’t such a big deal since they’re extremely similar. I decided to “frontload” my learning and start by mastering the foundational concepts: parsing, array rank, the rank operator, function rank, nested (i.e. successively applied) ranks, frames/cells, major cells ("items"), assembly and framing fill, empty arguments, frame agreement, enclose/box, indexing, the "each" and "every" operators, the i.-family of functions, and tacit combinators and trains (not foundational, but just too cool to put off learning about!). This indeed made everything else much easier to learn, as so many primitives can be elegantly expressed in terms of rank (especially the hairy stuff like inner/outer product, decode/encode, index-of, etc.). I learned these concepts from anywhere and everywhere concurrently—primarily from APL Wiki and NuVoc, but also from the NARS and BQN documentation pages, and the relevant chapters from Learning APL and Mastering Dyalog APL. I would recommend this way of learning!

Interests in Computing

I'm interested in learning ideas from BQN, K, Q, Jelly, and other array langs, particularly functional control structures that make use of first class functions, as I lean pretty heavily toward a functional style of programming, making heavy use of tacit expressions. I also eventually want to explore declarative langs like Prolog, which at a glance seems like it would be the ideal way of “programming”: purely declarative, just specify the constraints—no program to write.

One of my key interests in the array langs is learning subjects I never mastered and/or encountered in university—linear and multilinear algebra, vector and tensor calculus, relativity theory, quantum physics, etc., using APL/J to make each intensely interactive, in the style of the Coding the Matrix linear algebra textbook, which uses Python examples. (Certainly linear algebra and physics concepts are much more elegantly described in APL expressions than in conventional math notation.) APL-oriented college textbooks were common at one point, maybe in the 70’s.

This is on the back-burner for now, but I’m very much looking forward to exploring and mastering these fascinating subjects with APL! I’m sure I’ll end up building an APL-oriented course for each subject as I go through it, which I can then share with others. To me this style seems like the future of teaching/learning math-related subjects.

Also, I am particularly keen on helping to make learning these languages more accessible to others.

I ended up finding APL at the perfect time, right as Dyalog is filling in (at least most of) the remaining gaps in J's/BQN's combinator lexicon (atop, over, dyadic reverse-compose)! I feel like this is an exciting time for array languages, given recent developments like the creation of exploratory resources like APL Wiki, TryAPL, and the ArrayCast podcast; the online "learn APL" books; the J-inspired additions/extensions to Dyalog; the creation of Extended Dyalog, BQN, and dzaima/APL, which collectively extend the notation itself; the creation of Co-dfns, April, and ngn/APL; and the array-oriented tree manipulation strategies introduced by Co-dfns.

Potential future projects

Designing new array language:

I find myself wanting to create a new APL dialect that combines the leading features and concepts from Extended Dyalog and NARS (extended function domains), J (possibly function rank…?), BQN (first class functions, and maybe others), and k/q ("while" primitives similar to J's F[.:][.:]; elegant database interfacing). I'm leaning toward prefering a large set of convenient primitives (Jelly and Extended Dyalog are extreme exemplars) as opposed to the BQN philosophy of "it should be a primitive only if...". Certainly the truly essential/foundational primitives, and their essential sub-domains, should be partitioned separately from mere convenience primitives (e.g. J's Stitch and Laminate) in the documentation, though, for the purpose of learning the language. I'm thinking this could well be implemented in Singeli or Vex (frameworks for writing array languages, upon which BQN and April are implemented), or even a modification of the J source code (much less likely). I'm also considering introducing optional low-level resource control, e.g. memory management, since it sort of pains me to think that if someone wanted to develop an modern AAA video game in APL, they (apparently) currently wouldn't be able to (although maybe you could in April…? I'm not sure if Lisps allow such fine-grained control, but I don't expect so; plus I found interfacing with April to be painful). It would be nice to have an (open-source) APL that can be used practically for everything you'd want to use it for.

Proficiency level in APL and J

Currently I’m comfortable using 95–100% of APL primitives and maybe 90% of those from J (haven’t explored the combinatorics, linear algebra or calculus ones yet).

Areas yet to learn about: namespaces (so I can finally use Extended Dyalog!); error handling; debugging (admittedly a nightmare right now given APL’s nonexistent error reporting); object-oriented programming in APL/J/BQN; function control flow from BQN (and from K…?); scripting in Linux environment (GNU APL has this; not sure if Dyalog does); thread control; and all the system functions and interaction with the environment.

Tools

custom string mapping for entering APL glyphs

I’ve never used an APL keyboard mapping! Instead, in the Emacs text editor (Spacemacs, in my case), I use a custom string mapping (Xah Lee's Math Input Mode package) that associates input strings with corresponding characters to print. So I just enter gd<Shift><Space> for Grade Down , and even idioms like ax<Shift><Space> for ⍳≢⍴ (axes) and ax'<Shift><Space> for the tacit version ⍳∘≢∘⍴⍤. Truly coding at the speed of thought! The other advantage here is that it uses function mnemonics rather than glyph mnemonics—e.g. you can type either mi<Shift><Space> (Mix) or ta<Shift><Space> (Take) for the glyph , so you're typing in accordance with what you want to do, rather than having to type, say, "au" for the visual mnemonic "arrow up" corresponding to the glyph. Furthermore, you can type e.g. (<Shift><Space> for , and then <Shift><Space> again to change it to , coupling mnemonics in a natural way. Through successive <Shift><Space>'s you can cycle through ⊂⊆⊄⊈⊂—thus you can alternate between e.g. and by successive <Shift><Space>'s as well.

Even if you don't want to generally use Emacs as a text editor, switching between a small Emacs window and your APL IDE or command-line interpreter is trivial if you're using a tiled window manager (I use i3 or Sway). Sample workflow: type some APL code in Emacs, press <Esc>yy to copy the line of text, press <LogoKey>h to move the window focus leftward to the Dyalog interpreter, press <Ctrl>v to paste it in and evaluate it, then press <LogoKey>l to move back to the Emacs window—I find this a really convenient workflow.

Works in progress

frame agreement operator

I'm working on an operator to model frame agreement for any derived function f⍤l r, but currently it has some bugs, notably that the assert function causes _FA_ to give no result at all, in every case where it shouldn't give a length error:

      _FA_←{
           assert←{⍺←'LENGTH ERROR: one frame must be a prefix of the other' ⋄ 0∊⍵:⍺ ⎕SIGNAL 8 ⋄ void←0}
           r←1↓⌽3⍴⌽⍵⍵                      ⍝ dyadic ranks
           rm←r⌊∘(≢⍴)¨⍺ ⍵                  ⍝ modified ranks; rm⍲.≤(≢⍴)¨⍺ ⍵
           lf rf←(-rm)↓¨⍴¨⍺⍵               ⍝ frames
           cf←lf{⍺<⍥≢⍵:⍺ ⋄ ⍵}rf            ⍝ common frame, assuming frames agree
           k←{⍬≡⍵:99 ⋄ -≢⍵}cf              ⍝ relative rank; asymmetry: cf≡⍬ associated with ⍤99, not ⍤0
           assert ⍺∧⍥(cf≡(≢cf)↑⍴)⍵:        ⍝ verify that frames agree
           ⍺ ⍺⍺⍤⍵⍵⍤k⊢⍵
      }

      i←⊢⍴∘⍳×/                             ⍝ J's i.3 4 5
      x←i⊢2 3

      y←i⊢2 3 4 5

      ⍝ these should match:      (x{⍺⍵}_FA_ 1 2⊢y)  ≡  (x{⍺⍵}⍤1 2⍤¯1⊢y)

      x{⍺⍵}_FA_ 1 2⊢y
      ⍝ no result; somehow went to the end of the assert dfn