# Fast.ai APL study session 9

Fast.ai APL study session 9

Fast.ai APL study session 9

Discussion of the 9th study group can go here. Overview

[ <<< session 8 | [session 10 >>>]]

This is a wiki post - feel free to edit to add links from the lesson or other useful info.

## Study session covered:

• loop
• Atop vs Beside vs Over functions
• unique function (unique mask + replicate)
• inverse function
• fill element
• for reading Dyalog documentation (f=βΊβΊ, g=β΅β΅, X=βΊ, Y=β΅, R=Result)
2 Likes

The inverting power (pun intended) of `β£` is much greater than you demonstrated. It can both do non-mathematical things and seemingly impossible things.

The following function takes a three-letter word, reverses it, puts a space between the first and second letters, then prepends the letters `xyz`:

``````      fβ'xyz',1 0 1 1\β½
f 'ABC'
xyzC BA
``````

If we apply the inverse function on `'xyzC BA'` we should get back our `'ABC'`, right?

``````      (fβ£Β―1)'xyzC BA'
ABC
``````

It is seemingly impossible to solve 2x5+x4+5x3β2x2β6x=100, however:

``````      fβ(2Γ*β5)+(*β4)+(5Γ*β3)+(Β―2Γ*β2)+(Β―6βΓ)
(fβ£Β―1)100
2
f 2
100
``````

Thatβs one valid value for x.

2 Likes

You were trying to use `β¨` for removing the double mention of `v` in `v/β¨β v`. You can indeed do that, as you do want `v` as both left and right argument to `/β¨`. However, the right argument version of `v` much be preprocessed by `β `. βPre-process rightβ? Thatβs `fβg`:

``````      vβ22 10 22 22 21 10 5 10
/β¨ββ β¨v
22 10 21 5
Uniqβ/β¨ββ β¨
Uniq v
22 10 21 5
``````
1 Like

Another example of monadic use of β¨

``````x β 1 2 3
β The following three are equivalent and compute the array divided by its length
x Γ· (β΄ x)
x Γ·ββ΄ x
Γ·ββ΄β¨ x
β  Now we can use the above to compute the mean of an array
mean β +/β(Γ·ββ΄β¨)
``````

Or investigate trains:

``````mean β +/β(Γ·ββ΄β¨)
mean β +/(Γ·ββ΄β¨)    β atop: f g ββ fβg
mean β +/Γ·ββ΄β¨      β simplify: f ββ (f)
mean β +/Γ·β΄        β distributivity: (f g h)Y ββ (f Y)g(h Y)
``````
1 Like

Thanks. very cool. But the last one not equivalent and does not compute the mean of array, right?

``````+/Γ·β΄ 1 2 3  β this is just 0.33
``````

You have to put it in parentheses if you donβt assign it to a name first. Youβll see that @abrudz assigns it to a name.

1 Like

Thanks. `trains` seem useful (but not obvious). It may be a good concept to cover in the course. Maybe youβve covered it already. Iβve only watched up to middle of the 10th session.

As much as I enjoy APL (and your way of teaching it, in particular), I find it more like a cute and powerful puzzle framework than a practical programming language. As you said in ArrayCast podcast, I wish it was available as a module in python and swift to be used the same way RegExp are used within the language.

Iβm fairly confident that in a few months Iβll have a hard time making sense of APL expressions that I have written.

Itβs a real shame that some of the best and most paradigm changing languages come across like so. Maybe itβs because the current emphasis seems to be on winning obfuscated code contests and code golf competitions and making expressions as terse is possible (which, naturally, would scare the bajeezas out of mere mortals) but I think in its heyday, APL was used by regular office workers to do regular work. I think maybe because in those days of submitting jobs to the mainframes, your other options were COBOL, BASIC, PL1 or other beasts.

I found this page by a long time APLβer (Jerry Brennan) whose APL tutorial seems to cover more down to earth day to day problems. I also find Jerryβs tutorial quite approachable for myself (Iβm the eternal n00b unfortunately).

I mean, itβs good that some people have the advanced mental capacities to understand the rarified mathematical nuances of each operation, but some of us yerts just want to get some run of the mill stuff accomplished (like reading data in, cleaning it, maybe doing some EDA β¦ ) etc. etc.

Maybe itβs the nature of the beast? The more powerful and magical the language is, the bigger the probability that the practitioners of this βmagical artβ will become separated from the masses. Iβve seen it in Lisp and Forth as well, but APL is a totally new experience because the language is literally executable Math! I honestly feel like I need to know proper math before I an even use it for regular stuff.

I listen to the arraycast and I understand Iβm not the intended audience, but most of the time, I can appreciate that this is great content, but at the same time, I also frequently find myself saying , βI have no frikking idea what these dudes are talking aboutβ

At this stage weβre focused on getting thru all the glpyhs, so no we havenβt done trains yet. I expect after weβve finished the glyphs weβll do a session or two on tacit/point-free programming, including glyphs.

1 Like

No-one can remember things that they donβt practice retrieving. So yes, if you donβt keep working on it, youβll forget. Try using Anki with cards for all the glyphs you use, and for checking your understanding of some important combinations and concepts.

As you said in ArrayCast podcast, I wish it was available as a module in python and swift to be used the same way RegExp are used within the language.

You can use Dyalogβs `pynapl` that way: GitHub - Dyalog/pynapl: Dyalog APL ββ Python interface β see Rodrigoβs talk from Dyalog '21:

https://dyalog.tv/Dyalog21/?v=gOUFXBUMv_A

2 Likes

but some of us yerts just want to get some run of the mill stuff accomplished (like reading data in, cleaning it, maybe doing some EDA β¦ ) etc. etc.

Iβve gradually over time rewritten all my boring βworkβ stuff from Python to APL β an unholy bunch of utility scripts that typically gather data from a set of disparate sources (JSON-over-HTTP APIs mostly), massages, cleans, combines and otherwise aggregates it and spits out some report or other as json or csv. I built these as ]usercommands inside Dyalog, and to me it came as somewhat of a surprise both how nice it was to use APL this way, a million miles away from the cut and thrust of the code golferβs APL that we often see on display. The other realisation was that having created easy ways to get my data into Dyalog, Iβm much faster when it comes to cook up some combination that I hadnβt scripted for already. My codebase easily halved in size, even when writing APL in an expansive style.

I used to scoff at the tradfn-style of APL, but when youβre in βget stuffs doneβ mode, it can be super-helpful. APL (IMHO) is an excellent tool for doing boring data processing.

5 Likes

I totally agree, thereβs something to be said about empowering the masses with easily approachable computation! BTW, Iβm loving your current book, thanks for making it available to us all! maybe your next book could be βDo the boring stuff with APLβ

1 Like

I am very interested in knowing more about your workflow.
for example, do you get the JSON using python (using http requests) and then somehow feed it to your APL code and then use feed the output back to python? Do you use `pynapl` for doing this?

HttpCommand β Learning APL covers this - you can do http requests + json processing in APL just fine

2 Likes

Thanks. This is very helpful.
I installed `pynpal`. But `from pynapl import APL` asks for a password. Iβm sure Iβm doing something silly

Sure. So the first thing I had to wrap my head around was the concept of Dyalog user commands β at first glance, this (like many other APL things) seem utterly backwards. Normally, Iβd expect to interact with scripts I write in the unix shell, and enter switches or sub-commands as parameters. Doing this with APL in a reasonably portable way was until recently at best awkward or at worst hopeless.

Writing Dyalog user commands sort of inverts this pattern: you use Dyalog as the βshellβ and have it manage configuration and parameter passing, and simply write functions for the guts of your business logic. For this to be smooth, some of it works best as using the trad form, but this is mostly a wrapper.

@abrudz has a nice video on how to write your own user commands, and this is definitely the place to start if this sounds interesting. But basically, code you place in the directory `~/MyUCMDs` becomes available inside Dyalog as user commands. Below is a snippet of some of mine. The `List` and `Run` functions basically does the command-line processing, and in this example Iβve left in one of my βbusiness logicβ functions, called `defaults`, which fetches a json document, does a bit of grouping and reformatting. The weird function `dotcreds` just grabs the relevant credentials from a file.

To use this, I simply type `]CLUSTERS.defaults` into the Dyalog session.

As @rak1507 pointed out, I did write some stuff on how to do HTTP in Learn APL, and also a bit on json and friends. The `HttpCommand` http client lib is excellent.

``````:Namespace CLUSTERS
βIOβ0 β βMLβ1
hcββSE.SALT.Load'HttpCommand' β Dyalog HTTP client

baseβ'https://URL_HERE/'

dotcredsβ{βJSONβ 'Dialect' 'JSON5'β’2β½ '}}{"":{' , β'^;.*' '^\[(.*)]' '^(.*?)\s*=\s*(.*)'βR'' '},"\1":{' '"\1":"\2",' β’ ββNGET β΅}

credsβdotcreds '/Users/stefan/.creds'
hdβ1 2β΄'Authorization' (β,/'Basic '(hc.Base64Encode creds.section.user,':',creds.section.password))

β rβdefaults ;url;regions;names β Niladic; return cluster data for all region defaults
urlβbase,'broker-config/cloud-production' β Single doc
regβ(_βhc.GetJSON 'GET' url '' hd).Data.regions
rβget (β,/βͺ(regβΒ¨reg.βNLΒ―9).provisioning_cluster)
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β stuff removed for brevity
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β rβList
rββNSΒ¨20β΄ββ¬
r[0].(Name Group Desc Parse)β'Cluster'      'CLUSTERS' 'Cluster name'   '1S'
r[1].(Name Group Desc Parse)β'Defaults'     'CLUSTERS' 'Defaults'       ''
r[2].(Name Group Desc Parse)β'Plans'        'CLUSTERS' 'Plans'          ''
r[3].(Name Group Desc Parse)β'List'         'CLUSTERS' 'List'           ''
r[4].(Name Group Desc Parse)β'Plan'         'CLUSTERS' 'Plan name'      '1S'
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β stuff removed for brevity
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β

β rβRun(Cmd Input)
rββ¬
:Select Cmd
:Case 'Cluster'
rββget Input.Arguments
:Case 'Defaults'
rβdefaults
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β stuff removed for brevity
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
:Else
rββ'Unrecognised command'
:EndSelect
β

:EndNamespace
``````
1 Like

`pynapl` is in the process of being modernised; the maintainer goes by the moniker `@rgs` on the apl orchard, but Iβve not seen them here yet.