Introduction
I would like to show you how I got APL
working in emacs. You can interact with APL either through GNU-APL or through Dyalog-APL. I'll give you a quick rundown on both options.
Why use emacs?
I'm stubborn. I don't want to use RIDE for everything, even though it's capable. I like that I can bend emacs to do what I want. I also want to take notes on APL as I'm learning it through such wonderful resources as xpqz's introduction to APL. This setup lets you enter and evaluate APL using org-babel
blocks inside org-mode
. This might seem like a small thing, but there is so much insight you can gain by experimenting and just messing around with things. This method of interaction with the language encourages exploration and makes it easy.
GNU APL (gnu-apl-mode.el)
When we talk about this, we mean the wonderful emacs package by lokedhs. You will need this emacs package along-side an executable of gnu-apl on your system for this to work. This GNU implementation differs in syntax/glyphs from the Dyalog flavour of APL.
Pros
Native to emacs
Comes with cool input methods for typing glyphs (including the APL-Z layout)
Can show the APL keymap in a mini-buffer by calling
M-x gnu-apl-show-keyboard
once you have a session fired upYou can create plots using the in-built GNUPlot functions
The REPL is great
Everything is inspectable and customisable
Cons
The GNU implementation is not as widely used
Syntax/glyphs differ from what you may be used to with Dyalog APL
Documentation is sparse. You will find yourself reading the elisp to see how to do things (like plotting!)
Setup and use
The setup here is pretty simple. You can just load the package however you normally like. I'm using doom emacs, so in my packages.el
I have:
(package! gnu-apl-mode)
I then issue SPC h r r
to call doom/reload
, which will fetch and install the package. I'm on macOS, so I also went ahead and installed gnu-apl using brew:
brew install gnu-apl
This will install the executable on your system, which gnu-apl-mode
will then access and interact with.
To use this package, call gnu-apl
in emacs, which will create a repl buffer and initiate an APL session for you to mess around with.
Input is taken care of by gnu-apl-mode
which starts when the gnu-apl
buffer pops up. Check out the keyboard by calling gnu-apl-show-keyboard
. All keys are either prefixed by the super-key, or super-shift for the secondary layer. The APL-Z
input method is also included in the package. Call set-input-method
and select APL-Z
. This gives you the option to input glyphs using '.' as a leader key. For example, we want the glyph 'iota', we hit .i
and it prints ⍳
in our repl.
I use this input method when I am working with org-babel
blocks using the jupyter-apl kernel, which I will show you how to install in the next section.
Dyalog APL
I'm talking about the jupyter kernel for Dyalog APL, which is officially distributed by Dyalog.
Pros
The most widely used implementation of APL right now (2022)
Always being updated
Large community support
Great resources such as the APLWiki, APLcart and tatin.
Compatible with org-babel
Cons
Sometimes janky interaction with the jupyter-repl
Some massaging of the kernel necessary to work well in emacs
worse repl than with GNU APL (repl support through emacs-jupyter.el)
Setup and use
Setup is more involved than the native method. I will not cover setting up emacs-jupyter
, or installing jupyter
on your system (using PIP or otherwise). Those are the prerequisites. These are easily satisfied by using doom emacs, which does a lot of configuration work for you. Here are the steps:
Clone the repository for dyalog-jupyter and cd
into it. Go ahead and open kernel.py
(which lives in the 'dyalog_kernel' folder) in your favourite text editor (emacs). Search for the method out_result
and look for a dictionary named _content
. For me, it was on line 119. Inside of the _content
dictionary there are two definitions of the data
MIME-types. We want text/plain
for babel blocks. This is what they want to receieve from the kernel. Comment out the key/value pair which contains 'html'. It should look like this after you edit it:
def out_result(self, s): # injecting css: white-space:pre. Means no wrapping, RIDE SetPW will take care about line wrapping html_start = '<span style="white-space:pre; font-family: monospace">' html_end = '</span>' _content = { # 'output_type': 'display_data', 'data': {'text/plain': s}, #'data': {'text/html': html_start + html.escape(s, False) + html_end}, 'execution_count': self.execution_count, 'metadata': {}, # 'transient': '' }
After you've modified, go ahead and save this file. Go back to the project root and run the install script:
./install.sh
This should install the kernel to your jupyter
kernelspec list. Check if it worked by running:
jupyter lab
It should take you to the jupyter interface and in the list of available kernels you should see 'Dyalog APL'.
To run this in org-babel
, create a source block how you normally would and use jupyter-apl
as the kernelspec:
#+begin_src jupyter-apl :session *new* ⍳5
#+end_src
Hitting enter inside this block should give you a list as output. If you get an error saying something about jupyter, try to run this in your terminal:
pip3 install jupyter
and then re-run the install.sh
script in the dyalog-jupyter-kernel
folder you pulled from git.
As for entering glyphs, follow the input guide in the section on gnu-apl
and use the input method from that package.
Closing thoughts and wishlist
In all, what we have now is an excellent system for learning APL. With the org-babel
integration, we can use it in a multi-lingual and literate fashion. For example, you want to write a report and need to do some quick calculations on a couple of vectors. You can pop in a few APL src
blocks, show your workings and have the results neatly printed in your report. Want to graph or do some other manipulation that is cumbersome in APL? org-babel
has facilities which let you pass outputs from one language block to another. I haven't looked at this in depth yet, so can't give a demonstration in this post.
Wishlist
A proper 'face' for
jupyter-apl
src
blocks. Right now I'm turning offmixed-pitch-mode
, since my setup is giving the APL source code a 'proportionately spaced' typeface rather than the desired monospaced one.Syntax highlighting inside
src
blocks
Considerations
Check whether the font you use in emacs supports all the weird APL glyphs. Go to the APL wiki page on fonts and pick a nice one. I prefer PragmataPro Mono for monospaced text, and Source Sans Pro for proportionately spaced text.
Protesilaos Stavrou has a nice guide on fonts in emacs. Check that out if you're confused on fonts like I was