Rigorous Nonsense - On Hsu's Suggestivity and Idioms
Rigorous Nonsense
Home<br>Archive
On Hsu's Suggestivity and Idioms
Posted on July 24, 2023
by Brandon Wilson
Tags: apl
Recently, Aaron Hsu posted a nice article discussing a way in which APL’s<br>algebraic properties absolutely shine. The article ends up exhibits two<br>expressions—⍸2 and ⍸2>⌿⍵⍪0—which respectively pick the first and<br>last elements of groups of \(1\)s in a boolean mask.
The punchline being how the simple algebraic change— into<br>>—corresponds to meaningful semantics. This is precisely what Iverson’s<br>“Notation as a Tool of Thought” is about, also echoing the “power of good<br>notation” idea in 3Blue1Brown’s Triangle of Power video.
So, what about replacing with an arbitrary boolean function? Hsu gives a<br>nice table with the corresponding output, but the semantics of each are not<br>spelled out. Paul Mansour makes a head start in his Boolean Techniques<br>article, but I think we can go all the way:
Y 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 Description<br>{2⌿0⍪⍵}¨Y 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0-group head<br>{2>⌿1⍪⍵}¨Y 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0-group head, 1-boundary<br>{2>⌿⍵⍪0}¨Y 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1-group terminus<br>{2>⌿⍵⍪1}¨Y 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1-group terminus, 1-boundary<br>{2∧⌿0⍪⍵}¨Y 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1-group tail<br>{2∧⌿1⍪⍵}¨Y 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1-group tail, 1-boundary<br>{2∧⌿⍵⍪0}¨Y 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1-group non-termius<br>{2∧⌿⍵⍪1}¨Y 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1-group non-terminus, 1-boundary<br>{2⍲⌿0⍪⍵}¨Y 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 not 1-group tail<br>{2⍲⌿1⍪⍵}¨Y 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 not 1-group tail, 1-boundary<br>{2⍲⌿⍵⍪0}¨Y 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 not 1-group non-terminus<br>{2⍲⌿⍵⍪1}¨Y 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 not 1-group non-terminus, 1-boundary<br>{2∨⌿0⍪⍵}¨Y 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 not 0-group tail<br>{2∨⌿1⍪⍵}¨Y 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 not 0-group tail, 1-boundary<br>{2∨⌿⍵⍪0}¨Y 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 not 0-group non-terminus<br>{2∨⌿⍵⍪1}¨Y 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 not 0-group non-terminus, 1-boundary<br>{2⍱⌿0⍪⍵}¨Y 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0-group tail<br>{2⍱⌿1⍪⍵}¨Y 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0-group tail, 1-boundary<br>{2⍱⌿⍵⍪0}¨Y 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0-group non-terminus<br>{2⍱⌿⍵⍪1}¨Y 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0-group non-terminus, 1-boundary<br>{2⊢⌿0⍪⍵}¨Y 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 id<br>{2⊢⌿1⍪⍵}¨Y 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 id<br>{2⊢⌿⍵⍪0}¨Y 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 0 left-shift, 0-insert<br>{2⊢⌿⍵⍪1}¨Y 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 1 left-shift, 1-insert<br>{2⊣⌿0⍪⍵}¨Y 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 right-shift, 0-insert<br>{2⊣⌿1⍪⍵}¨Y 1 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 right-shift, 1-insert<br>{2⊣⌿⍵⍪0}¨Y 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 id<br>{2⊣⌿⍵⍪1}¨Y 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 id<br>It is interesting to note that the naming scheme can be thought as a simple<br>re-parameterization of the algebraic phrases. In particular, we have
\[ \begin{aligned}<br>48 &= \textrm{#functions} \\<br>&= B \cdot e \cdot d \\<br>&= 12 \cdot 2 \cdot 2<br>\end{aligned} \]
where
\(B\) denotes the \(12\) count of binary functions you chose, which ignores the<br>other four binary functions, 0⍨, 1⍨, ~⍤⊢, and ~⍤⊣,
\(e\) denotes the \(2\) choices, \(0\) or \(1\), of edge conditions, and
\(d\) denotes the \(2\) choices, pre- or post-pending, of direction.
Whereas the semantic descriptions partition the collection differently:
\[ \begin{aligned}<br>48 &= \textrm{#functions} \\<br>&= g \cdot p \cdot d \cdot b \cdot i + A + S + I \\<br>&= 2 \cdot 2 \cdot 2 \cdot 2 \cdot 2 + 8 + 4 + 4<br>\end{aligned} \]
where
\(g\) denotes the choice of selecting on either \(0\)- or \(1\)-groups,
\(p\) denotes the selecting the group head or tail,
\(d\) denotes the choice of “direction”, i.e. forwards selects head or tail and<br>reverse selects terminus or non-terminus,
\(b\) denotes the choice of \(0\) or \(1\) boundary condition,
\(i\) denotes the choice of whether selection is inverted or not,
\(A\) is the class of group-agnostic functions,
\(S\) is the special class of shift functions,...