1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
<head>
<link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
<link href="../style.css" rel="stylesheet"/>
<title>Problems with BQN</title>
</head>
<div class="nav"><a href="https://github.com/mlochbaum/BQN">BQN</a> / <a href="../index.html">main</a> / <a href="index.html">commentary</a></div>
<h1 id="problems-with-bqn">Problems with BQN</h1>
<p>Every language has some issues that everyone can agree make programming harder. Sometimes there is a simple solution that has not yet been discovered; sometimes the problem is inherent to the language because it's caused by fundamental choices (or anywhere in between). Below are problems I have identified in BQN, ordered from what I consider the most severe to the least. This is independent of whether the issue can be solved—if it somehow went away, how much better would the language be?</p>
<p>I've omitted problems that are obviously addressed by speculated extensions. Of course adding A fixes the problem "doesn't have A". Problems that only exist in reference to some existing convention (e.g. unfamiliarity to APLers) are also left out, unless the convention manifests technically (Unicode support).</p>
<h3 id="empty-arrays-lose-type-information">Empty arrays lose type information</h3>
<p>A pretty fundamental problem with dynamically-typed array languages. Prototypes are intended to solve it, but they don't really. It doesn't help that the notion of type is fluid: elements of an array in one moment can be axis lengths in the next; did the numeric value go from not being type information to being type information? Inferred type might help here, particularly the ability of one part of the program to ask another part for type information during compilation. But that needs to be specified if programmers are going to rely on it, which sounds difficult.</p>
<h3 id="incoherent-monad-dyad-builtin-pairs">Incoherent monad-dyad builtin pairs</h3>
<p>BQN inherits the functions <code><span class='Function'>+×⌊⌈|</span></code>, and adds the functions <code><span class='Function'>∧∨<>≠≡≢↕⍷</span></code>, that are only paired for their glyphs and not for any other reason (that is, both function valences match the symbol but they don't match with each other). I find there are just not enough good glyphs to separate all of these out, but I'm sure the pairings could be improved.</p>
<h3 id="glyphs-are-hard-to-type">Glyphs are hard to type</h3>
<p>There's been a lot of work done on this. Still there, still a problem. On the other hand, glyphs are easy to read, and write by hand!</p>
<h3 id="tacit-and-one-line-functions-are-hard-to-debug">Tacit and one-line functions are hard to debug</h3>
<p>This problem hasn't manifested yet as BQN has no debugger, but it's something to keep in mind. Traditional line-by-line debuggers don't work when the line is doing so much work. Something like J's dissect or some kind of hybrid would probably do better.</p>
<h3 id="search-function-depth">Search function depth</h3>
<p>The simplest way to define a search function like Index Of is to require the left argument to be a list, and search for an element that matches the right argument. But this means you can only search for one element at a time, which is annoying and doesn't work for Progressive Index Of. So we instead treat the searched argument as a list of major cells. Then we decide to search for cells of the other argument that have the same rank as those cells, since only cells with the same rank can match. That's a little strange for Bins, where it still makes sense to compare cells of different ranks. Furthermore, the result of any search function is always an array. To search for a single element and get an plain number, you need something like <code><span class='Value'>list</span><span class='Modifier2'>⊸</span><span class='Function'>⊐</span><span class='Modifier2'>⌾</span><span class='Function'><</span><span class='Value'>elt</span></code>.</p>
<h3 id="trigonometry">Trigonometry</h3>
<p>There are a lot of standard functions and I don't want to use separate primitives or a menu-style primitive like APL Circle for them. You can define all the functions eventually if you use complex exponential and take real and imaginary parts and inverses, but this doesn't sound well-suited for implementation. And there should be a math library that gives you the standard functions with normal names, but how will it be implemented?</p>
<h3 id="right-to-left-multi-line-functions-go-upwards">Right-to-left multi-line functions go upwards</h3>
<p>If you include multiple multi-line functions in what would otherwise be a one-liner, the flow in each function goes top to bottom but the functions are executed bottom to top. I think the fix here is to just say give your functions names and don't do this.</p>
<h3 id="control-flow-substitutes-have-awkward-syntax">Control flow substitutes have awkward syntax</h3>
<p>At the moment BQN has no control structures, instead preferring modifiers, function recursion, and headers. When working with pure functions, these can be better than control structures. For more imperative programming they're a lot worse. For example, it's natural to have two arguments for small structures, but that becomes unreadable for larger ones. However, predefined functions acting on functions can cover a lot of ground for the imperative programmer; see <a href="../doc/control.html">Control flow in BQN</a>.</p>
<p>One particular sore point with Repeat (<code><span class='Modifier2'>⍟</span></code>) and Choose (<code><span class='Modifier2'>◶</span></code>) is that the condition and action(s) always apply to the same set of arguments. Often you'd like them to apply to completely different things: this seems like the sort of thing that split compose <code><span class='Function'>F</span><span class='Modifier2'>⊸</span><span class='Function'>G</span><span class='Modifier2'>⟜</span><span class='Function'>H</span></code> solved for trains, but here there's no such solution.</p>
<h3 id="hard-to-search-part-of-an-array-or-in-a-different-order">Hard to search part of an array or in a different order</h3>
<p>This includes index-of-last, and searching starting at a particular index, when the desired result indices are to the array to be seached <em>before</em> it is modified. Given indices <code><span class='Value'>i</span></code> into an array <code><span class='Value'>𝕨</span></code> (for example <code><span class='Function'>⌽↕≠</span><span class='Value'>𝕨</span></code> or <code><span class='Value'>a</span><span class='Function'>+↕</span><span class='Value'>b</span></code>), this section can be searched with <code><span class='Paren'>(</span><span class='Value'>i</span><span class='Function'>∾≠</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>⊏</span><span class='Modifier'>˜</span><span class='Paren'>(</span><span class='Value'>i</span><span class='Function'>⊏</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>⊐</span><span class='Value'>𝕩</span></code>. But this is clunky and difficult for the implementation to optimize.</p>
<h3 id="subtraction-division-and-span-are-backwards">Subtraction, division, and span are backwards</h3>
<p>The left argument feels much more like the primary one in these cases (indeed, this matches the typical left-to-right ordering of binary operators in mathematics). The commonly-paired <code><span class='Function'>⌊</span><span class='Modifier2'>∘</span><span class='Function'>÷</span></code> and <code><span class='Function'>|</span></code> have opposite orders for this reason. Not really fixable; too much precedent.</p>
<h3 id="syntactic-type-erasure">Syntactic type erasure</h3>
<p>A programmer can call a modifier on either a syntactic function or subject, but there's no way to know within the modifier which syntax that operand had. Maybe this is a better design, but it doesn't feel quite right that <code><span class='Value'>f</span><span class='Modifier'>˜</span></code> is <code><span class='Value'>f</span></code>-Swap if <code><span class='Value'>f</span></code> has a function value. The subject syntax suggests it should be Constant. Instead the Constant modifier <code><span class='Modifier'>˙</span></code> has been added partially to mitigate this.</p>
<h3 id="nothing--interacts-strangely-with-before-and-after">Nothing (<code><span class='Nothing'>·</span></code>) interacts strangely with Before and After</h3>
<p>Since <code><span class='Value'>𝕨</span><span class='Function'>F</span><span class='Modifier2'>⊸</span><span class='Function'>G</span><span class='Value'>𝕩</span></code> is <code><span class='Paren'>(</span><span class='Function'>F</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>G</span><span class='Value'>𝕩</span></code> and <code><span class='Value'>𝕨</span><span class='Function'>F</span><span class='Modifier2'>⟜</span><span class='Function'>G</span><span class='Value'>𝕩</span></code> is <code><span class='Value'>𝕨</span><span class='Function'>F</span> <span class='Function'>G</span><span class='Value'>𝕩</span></code> in the dyadic case, we might expect these to devolve to <code><span class='Function'>G</span><span class='Value'>𝕩</span></code> and <code><span class='Function'>F</span> <span class='Function'>G</span><span class='Value'>𝕩</span></code> when <code><span class='Value'>𝕨</span></code> is not present. Not so: instead <code><span class='Value'>𝕩</span></code> is substituted for the missing <code><span class='Value'>𝕨</span></code>. And Before and After are also the main places where a programmer might try to use <code><span class='Value'>𝕨</span></code> as an operand, which doesn't work either (the right way is the train <code><span class='Value'>𝕨</span><span class='Function'>F⊢</span></code>). It's also a little strange that <code><span class='Value'>v</span> <span class='Function'>F</span><span class='Modifier'>˜</span><span class='Nothing'>·</span></code> is <code><span class='Nothing'>·</span></code>, while <code><span class='Nothing'>·</span><span class='Function'>F</span> <span class='Value'>v</span></code> is <code><span class='Function'>F</span> <span class='Value'>v</span></code>.</p>
<h3 id="cant-access-array-ordering-directly">Can't access array ordering directly</h3>
<p>Only <code><span class='Function'>⍋⍒</span></code> use array ordering rather than just array equality or numeric ordering. Getting at the actual ordering to just compare two arrays is more difficult than it should be (but not <em>that</em> difficult: <code><span class='Function'>⥊</span><span class='Modifier2'>⊸</span><span class='Function'>⍋</span><span class='Modifier2'>⌾</span><span class='Function'><</span></code> is TAO <code><span class='Function'>≤</span></code>).</p>
<h3 id="comparison-tolerance">Comparison tolerance</h3>
<p>Kind of necessary for practical programming, but how should it be invoked or controlled? A system variable like <code><span class='Value'>⎕</span><span class='Function'>CT</span></code>? Per-primitive control? Both? Which primitives should use it?</p>
<table>
<thead>
<tr>
<th>Definitely</th>
<th>Maybe</th>
<th>Definitely not</th>
</tr>
</thead>
<tbody>
<tr>
<td><code><span class='Function'>=≠≤≥<></span></code></td>
<td><code><span class='Function'>≡≢⊐⊒∊⍷|</span></code></td>
<td><code><span class='Function'>⍋⍒</span></code></td>
</tr>
</tbody>
</table>
<h3 id="no-access-to-fast-high-precision-sum">No access to fast high-precision sum</h3>
<p>Fold has a specific order of application, which must be used for <code><span class='Function'>+</span><span class='Modifier'>`</span></code>. But other orders can be both faster and more precise (in typical cases) by enabling greater parallelism. Generally ties into the question of providing precision control for a program: it could be fixed by a flag that enables BQN to optimize as long as the results will be at least as precise (relative to the same program in infinite precision) as the spec.</p>
<h3 id="assert-has-no-way-to-compute-the-error-message">Assert has no way to compute the error message</h3>
<p>In the compiler, error messages could require expensive diagnostics, and in some cases the message includes parts that can only be computed if there's an error (for example, the index of the first failure). However, Assert (<code><span class='Function'>!</span></code>) only takes a static error message, so you have to first check a condition, then compute the message, then call Assert with <code><span class='Number'>0</span></code> as its right argument. Very ugly. This is generally going to be an issue for high-quality tools built in BQN, where giving the user good errors is a priority.</p>
<h3 id="high-rank-array-notation">High-rank array notation</h3>
<p>The proposed Dyalog array notation <code><span class='Value'>[]</span></code> for high-rank arrays: it's the same as BQN's lists <code><span class='Bracket'>⟨⟩</span></code> except it mixes at the end. This works visually because the bottom level—rows—is written with stranding. It also looks okay with BQN strands but clashes with BQN lists. At that point it becomes apparent that specifying whether something is a high-rank array at the top axes is kind of strange: shouldn't it be the lower axes saying to combine with higher ones?</p>
<h3 id="list-splicing-is-fiddly">List splicing is fiddly</h3>
<p>It's common when manipulating text to want to replace a slice with a different slice with an unrelated length. Structural Under works well for this if the new slice has the same length but doesn't otherwise (an implementation could choose to support it, but <em>only</em> if the slice is extracted using two Drops, not Take). So in general the programmer has to cut off initial and final segments and join them to the new slice. If the new slice is computed from the old one it's much worse, as there will be duplication between the code to extract that slice and the other segments. The duplication can be avoided with Group using <code><span class='Function'>∾F</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Number'>1</span><span class='Modifier2'>⊸</span><span class='Function'>⊑</span><span class='Paren'>)(</span><span class='Value'>s</span><span class='Ligature'>‿</span><span class='Value'>e</span><span class='Function'>⍋↕</span><span class='Modifier2'>∘</span><span class='Function'>≠</span><span class='Paren'>)</span><span class='Modifier2'>⊸</span><span class='Function'>⊔</span></code>, but this is a lot of work and will execute slowly without some special support. In fact, everything here is liable to run slowly, making too many copies of the unmodified part of the stream.</p>
<p>Dyalog's solution here (and dzaima/BQN's) is Regex, which is a nice feature but also an entire second language to learn.</p>
<h3 id="cant-always-transfer-ambivalence-in-tacit-code">Can't always transfer ambivalence in tacit code</h3>
<p>For example, there's no tacit equivalent of the old APL (NARS) <code><span class='Modifier2'>∘</span></code>, which in explicit BQN is simply <code><span class='Brace'>{</span><span class='Value'>𝕨</span><span class='Function'>𝔽𝔾</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>. Similarly, <code><span class='Brace'>{</span><span class='Paren'>(</span><span class='Function'>𝔽</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code> is missing. The contrast with Atop and Over, which work very smoothly, can be jarring and make it harder to get an intuition for what the code is doing.</p>
<h3 id="poor-font-support-">Poor font support</h3>
<p>Characters <code><span class='Function'>⥊∾</span><span class='Modifier2'>⟜⎉⚇</span><span class='Modifier'>˜</span></code> and double-struck letters are either missing from many fonts or drawn strangely.</p>
<h3 id="choose-and-repeat-have-order-swapped">Choose and Repeat have order swapped</h3>
<p>In Choose, the selector goes on the left; in Repeat, the count goes on the right. Could be a strength in some contexts, since you can change Repeat-as-If to Choose if you don't like the ordering, but maybe a language that forces the programmer to make semantic decisions for syntactic reasons is not providing the greatest of services.</p>
<h3 id="index-of-privileges-the-first-match">Index Of privileges the first match</h3>
<p>It could be more sound to look at all matches, but using just the first one is too convenient. J has an index-of-last function; in BQN you have to reverse the left argument and then do arithmetic: <code><span class='Function'>≠</span><span class='Modifier2'>∘</span><span class='Function'>⊣-</span><span class='Number'>1</span><span class='Function'>+⌽</span><span class='Modifier2'>⊸</span><span class='Function'>⊐</span></code>.</p>
<h3 id="glyphs-that-arent-great">Glyphs that aren't great</h3>
<p>Blanket issue for glyphs that need work. Currently I find <code><span class='Function'>⥊⊏⊑⊐⊒⍷</span><span class='Modifier'>⁼</span><span class='Modifier2'>⎉⚇</span></code> to not be particularly good fits for what they describe.</p>
<h3 id="cant-mix-define-and-modify-in-multiple-assignment">Can't mix define and modify in multiple assignment</h3>
<p>Say <code><span class='Value'>a</span></code> is a pair and <code><span class='Value'>h</span></code> isn't defined yet; how would you set <code><span class='Value'>h</span></code> to the first element of <code><span class='Value'>a</span></code> and change <code><span class='Value'>a</span></code> to be just the second? <code><span class='Value'>h</span><span class='Ligature'>‿</span><span class='Value'>a</span><span class='Gets'>↩</span><span class='Value'>a</span></code> doesn't work because <code><span class='Value'>h</span></code> isn't defined, so the best I have is <code><span class='Value'>h</span><span class='Gets'>←</span><span class='String'>@</span><span class='Separator'>⋄</span><span class='Value'>h</span><span class='Ligature'>‿</span><span class='Value'>a</span><span class='Gets'>↩</span><span class='Value'>a</span></code>. A heavier assignment syntax wouldn't break down; BQN could allow <code><span class='Bracket'>⟨</span><span class='Value'>h</span><span class='Gets'>←</span><span class='Separator'>,</span><span class='Value'>a</span><span class='Bracket'>⟩</span><span class='Gets'>↩</span><span class='Value'>a</span></code> but I don't think this merits special syntax.</p>
<h3 id="trains-dont-like-monads">Trains don't like monads</h3>
<p>If you have the normal mix of monads and dyads you'll need a lot of parentheses and might end up abusing <code><span class='Modifier2'>⟜</span></code>. Largely solved with the "nothing" glyph <code><span class='Nothing'>·</span></code>, which acts like J's Cap (<code><span class='Value'>[:</span></code>) in a train, but still a minor frustration.</p>
<h3 id="underbind-combination-is-awkward">Under/bind combination is awkward</h3>
<p>It's most common to use Under with dyadic structural functions in the form <code><span class='Value'>…</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Value'>i</span><span class='Modifier2'>⊸</span><span class='Function'>F</span><span class='Paren'>)</span></code>, for example where <code><span class='Function'>F</span></code> is one of <code><span class='Function'>/</span></code> or <code><span class='Function'>↑</span></code>. This is frustrating for two reasons: it requires parentheses, and it doesn't allow <code><span class='Value'>i</span></code> to be computed tacitly. If there's no left argument then the modifier <code><span class='Brace'>{</span><span class='Function'>𝔽</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Value'>𝕨</span><span class='Modifier2'>⊸</span><span class='Function'>𝔾</span><span class='Paren'>)</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code> can be more useful, but it doesn't cover some useful cases such as mask <code><span class='Value'>a</span> <span class='Function'>⊣</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Value'>u</span><span class='Modifier2'>⊸</span><span class='Function'>/</span><span class='Paren'>)</span> <span class='Value'>b</span></code>.</p>
<h3 id="axis-ordering-is-big-endian">Axis ordering is big-endian</h3>
<p>The most natural ordering for polynomial coefficients and base representations is little-endian, because it aligns element <code><span class='Value'>i</span></code> of the list with power <code><span class='Value'>i</span></code> of the argument or base. It also allows a forward scan instead of a reverse one. Array axes go the other way. However, there are advantages to this ordering as well. For example, it's common to act only on the first few axes, so having them at the beginning of the array is good (<code><span class='Function'>≠</span><span class='Value'>a</span> <span class='Gets'>←→</span> <span class='Function'>⊑</span><span class='Modifier2'>∘</span><span class='Function'>≢</span><span class='Value'>a</span></code>).</p>
<h3 id="inverse-is-not-fully-specified">Inverse is not fully specified</h3>
<p>So it seems a bit strange to rely on it for core language features like <code><span class='Function'>/</span><span class='Modifier'>⁼</span></code>. On the other hand, this is a good fit for <code><span class='Function'>⋆</span><span class='Modifier'>⁼</span></code> since we are taking an arbitrary branch of a complex function that has many of them. I'm pretty sure it's impossible to solve the issue as stated but it might be possible to move to less hazardous constructs. Structural Under is a start.</p>
<h3 id="group-doesnt-include-trailing-empty-groups">Group doesn't include trailing empty groups</h3>
<p>A length can now be specified either in an extra element in any rank-1 component of <code><span class='Value'>𝕨</span></code>, or by overtaking, since the result's fill element is an empty group. However, it still seems like it would be pretty easy to end up with a length error when a program using Group encounters unexpected data. It's a fundamental safety-convenience tradeoff, though, because specifying a length has to take more code in the general case.</p>
<h3 id="prefixessuffixes-add-depth-and-windows-doesnt">Prefixes/Suffixes add depth and Windows doesn't</h3>
<p>It's an awkward inconsistency. Prefixes and Suffixes have to have a nested result, but Windows doesn't have to be flat; it's just that making it nested ignores the fact that it does have an array structure.</p>
<h3 id="deshape-and-reshape-cant-ignore-trailing-axes">Deshape and Reshape can't ignore trailing axes</h3>
<p>If you want to repeat 3 major cells until there are 7 of them, or combine the first 4 axes of a rank-6 array, what's your best option? Nothing's too good: you could compute a full shape for Reshape, enclose cells and merge afterwards (for example <code><span class='Number'>7</span><span class='Modifier2'>⊸</span><span class='Function'>⥊</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Function'><</span><span class='Modifier'>˘</span><span class='Paren'>)</span></code>), use Select to reshape one axis to multiple, or use <code><span class='Function'>∾</span><span class='Modifier'>˝</span></code> to merge two axes (with possible empty-array issues). This is particularly dangerous with computed-length reshapes like <code><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Modifier2'>∘</span><span class='Function'>⥊</span><span class='Value'>…</span></code>, since the idea of splitting off a length-2 axis from an array's first axis is generally useful, but this version has an implicit Deshape first. J's Reshape analogue (<code><span class='Value'>$</span></code>) only ever applies to the first axis. This also seems to be giving up a lot.</p>
<h3 id="at-which-scope-does-a-block-function-belong">At which scope does a block function belong?</h3>
<p>As a general principle, a programmer should make choices in one part of a program that constrain other parts of the program most tightly. This is a weak principle, but often it doesn't conflict with any other preferences and can be followed for free. For example it's usually best to define a variable in the smallest possible scope, so the reader knows it isn't used outside that scope. The same principle applies to blocks, but there is another conflicting principle: placing the block in a broader scope guarantees it won't access the variables in narrower ones. There's no position that will tell the reader, for example, that a function only uses variables local to itself and that it's only used within one particular scope.</p>
<p>This is an issue with any lexically-scoped language; it's unlikely BQN can solve it. On the other hand, I'm surprised I've never seen any discussion of such a universal issue.</p>
<h3 id="rankdepth-negative-zero">Rank/Depth negative zero</h3>
<p>A positive operand to Rank indicates the cell rank, so positive zero means to act on 0-cells. A negative operand indicates the frame length, so negative zero should act on the entire array. But it can't because it's equal to positive zero. Similar issue with Depth. Positive/negative is not really the right way to encode the frame/cell distinction, but it's convenient. Fortunately ∞ can be used in place of negative zero, but there can still be problems if the rank is computed.</p>
<h3 id="tacit-code-cant-build-lists-easily">Tacit code can't build lists easily</h3>
<p>It's unergonomic, and also quadratic in a naive runtime. The problem of course is that tacit code can only combine up to two values at a time, while in explicit code, list notation combines any number of them. In a language less beholden to syntax, <code><span class='Function'>List</span></code> would simply be a function with an arbitrary number of arguments and you'd be able to form trains with it—although this <em>does</em> require distinguishing when it's used as a train versus as a plain function.</p>
<h3 id="must-read-the-body-to-find-headerless-blocks-type">Must read the body to find headerless block's type</h3>
<p>You have to scan for headers or double-struck names (and so does a compiler). A little inelegant, and difficult to describe in BNF. This can usually be fixed by adding a block header, except in the case of immediate modifiers: even an immediate modifier with a header can be made into a deferred modifier by adding a special name like <code><span class='Value'>𝕨</span></code>.</p>
<h3 id="no-one-right-way-to-check-if-a-value-is-an-array">No one right way to check if a value is an array</h3>
<p>The mathematical approach is <code><span class='Number'>0</span><span class='Function'><≡</span><span class='Value'>𝕩</span></code>, which can be slow without runtime support, while the efficient approach is <code><span class='Number'>0</span><span class='Function'>=•Type</span><span class='Value'>𝕩</span></code>, which is ugly and uses a system function for something that has nothing at all to do with the system. These are minor flaws, but programmers shouldn't have to hesitate about which one they want to use.</p>
<h3 id="each-block-body-has-its-own-label">Each block body has its own label</h3>
<p>In a block with multiple bodies, the label (the self-name part of the header) refers to the entire block. However, there's no way to give only one label to the entire block. If you want to consistently use the same internal name, then you may have to write it many times. It's also a weird mismatch, conceptually.</p>
<h3 id="have-to-be-careful-about-intermediate-results-with-affine-characters">Have to be careful about intermediate results with affine characters</h3>
<p>A computation like <code><span class='Paren'>(</span><span class='Value'>a</span><span class='Function'>+</span><span class='Value'>b</span><span class='Paren'>)</span><span class='Function'>÷</span><span class='Number'>2</span></code> (midpoint between characters <code><span class='Value'>a</span></code> and <code><span class='Value'>b</span></code>, of the distance between them is even) or <code><span class='Number'>5</span><span class='Function'>></span><span class='Value'>v</span><span class='Function'>-</span><span class='Value'>n</span></code> (equivalent to <code><span class='Value'>v</span><span class='Function'><</span><span class='Number'>5</span><span class='Function'>+</span><span class='Value'>n</span></code>) is conceptually okay, but the first will always fail because <code><span class='Value'>a</span><span class='Function'>+</span><span class='Value'>b</span></code> is invalid while the second will (even worse!) fail only if <code><span class='Value'>v</span></code> is a character with code point smaller than <code><span class='Value'>n</span></code>. Arithmetic manipulations that would be valid for numbers aren't for the number-character system.</p>
<p>Numbers and characters are subsets of a linear space with components "characterness" (0 for numbers and 1 for characters) and value (code point for characters). Numbers are a linear subspace, and characters a subset of an affine one. Their union isn't closed under addition and subtraction in either component. Usually this is good, as failing when the user creates a nonexistent character or double-character can catch a lot of errors. But not always.</p>
<h3 id="monadic-argument-corresponds-to-left-for--and-">Monadic argument corresponds to left for <code><span class='Function'>/</span></code> and <code><span class='Function'>⊔</span></code></h3>
<p>Called dyadically, both functions shuffle cells of the right argument around, which is consistent with other selection-type functions. But the monadic case applies to what would be the left argument in the dyadic case.</p>
<h3 id="hard-to-manipulate-the-result-of-a-modifier">Hard to manipulate the result of a modifier</h3>
<p>Trains and compositions make it easy to work with the results of functions, in some sense. The same can't be said for modifiers: for example, in a non-immediate block modifier, the derived function is <code><span class='Function'>𝕊</span></code>, but you can't apply <code><span class='Modifier'>˜</span></code> to it. This seems to call for modifer trains but people who worked with early J are confident they're not worth it. Or were they just not designed right?</p>
<h3 id="monadic--versus-">Monadic <code><span class='Function'>⊑</span></code> versus <code><span class='Function'>></span></code></h3>
<p>Both pull out elements and reduce the depth. But they face in opposite directions. However, neither should be thought of as the inverse to <code><span class='Function'><</span></code>: that's <code><span class='Function'><</span><span class='Modifier'>⁼</span></code>. And <code><span class='Function'>></span></code> can't reduce the depth to 0, so it's pretty different from <code><span class='Function'>⊑</span></code> or <code><span class='Function'><</span><span class='Modifier'>⁼</span></code>.</p>
<p>The directions of <code><span class='Function'>⊏⊐</span></code> and so on were mainly chosen to line up with <code><span class='Function'>∊</span></code>: the argument that indices apply to (that is, the one that is searched or selected from) corresponds to the open side of the function. I'd probably prefer new glyphs that don't have this sort of directionality, however.</p>
<h3 id="cant-take-prefixes-or-suffixes-on-multiple-axes">Can't take Prefixes or Suffixes on multiple axes</h3>
<p>This is a natural array operation to do, and results in an array with a joinable structure, but as Prefixes and Suffixes are monadic there's no way to specify the number of axes to use.</p>
<h3 id="modified-assignment-modifies-the-left-secondary-argument">Modified assignment modifies the left (secondary) argument</h3>
<p>So you end up with <code><span class='Modifier'>˜</span><span class='Gets'>↩</span></code> a lot of the time. For ordinary assignment it's pretty reasonable to say the value is primary, but modified assignment flips this around.</p>
<h3 id="andormaxmin-are-all-tangled-up">And/Or/Max/Min are all tangled up</h3>
<p>Boolean And (<code><span class='Function'>∧</span></code>) and Or (<code><span class='Function'>∨</span></code>) are identical to Min (<code><span class='Function'>⌊</span></code>) and Max (<code><span class='Function'>⌈</span></code>) when restricted to Boolean arguments, and this would fit nicely with their monadic role as sorting functions: for example <code><span class='Value'>a</span><span class='Function'>∧</span><span class='Value'>b</span> <span class='Gets'>←→</span> <span class='Function'>⊑∧</span><span class='Value'>a</span><span class='Ligature'>‿</span><span class='Value'>b</span></code>. Furthermore the pairing of Min with Floor and Max with Ceiling is mnemonic only and not especially natural. The reason I have not used these glyphs for Min and Max, and have instead extended them to the somewhat superfluous <a href="../doc/logic.html">arithmetic logical functions</a> is that Min and Max have different <a href="https://aplwiki.com/wiki/Identity_element">identity elements</a> of <code><span class='Number'>∞</span></code> and <code><span class='Number'>¯∞</span></code> rather than <code><span class='Number'>1</span></code> and <code><span class='Number'>0</span></code>. Having to code around empty arrays when using <code><span class='Function'>∧</span><span class='Modifier'>´</span></code> would be a fairly big issue.</p>
<p>The other drawback of Min (<code><span class='Function'>∧</span></code>) and Max (<code><span class='Function'>∨</span></code>) is that the symbols are counterintuitive, but I have found a way to remember them: consider the graph of variables <code><span class='Value'>a</span><span class='Gets'>←</span><span class='Value'>x</span></code> and <code><span class='Value'>b</span><span class='Gets'>←</span><span class='Function'>¬</span><span class='Value'>x</span></code> for x from 0 to 1: two crossed lines. Now the graph of <code><span class='Value'>a</span><span class='Function'>∧</span><span class='Value'>b</span></code> is a caret shape and <code><span class='Value'>a</span><span class='Function'>∨</span><span class='Value'>b</span></code> is a vee.</p>
<h3 id="acting-on-windows-can-be-awkward">Acting on windows can be awkward</h3>
<p>When taking Windows along more than one axis, acting on the resulting array requires the Rank modifier, duplicating either the right argument rank or (negated) left argument length. A nested Windows would only require Each.</p>
<h3 id="inputs-to-modifiers-are-called-operands">Inputs to modifiers are called operands?</h3>
<p>"Operand" is derived from "operator". "Modificand" would be better if it weren't both made up and hideous.</p>
<h3 id="converting-a-function-expression-to-a-subject-is-tricky">Converting a function expression to a subject is tricky</h3>
<p>You can name it, you can write <code><span class='Function'>⊑</span><span class='Bracket'>⟨</span><span class='Function'>Expr</span><span class='Bracket'>⟩</span></code> or <code><span class='Paren'>(</span><span class='Function'>Expr</span><span class='Paren'>)</span><span class='Modifier'>˙</span><span class='Number'>0</span></code>, and if it doesn't use special names you can write <code><span class='Brace'>{</span><span class='Function'>Expr</span><span class='Brace'>}</span></code>. All of these are at least a little awkward in reasonable cases. Should there be a dedicated syntax? Note that going the other way, from subject to function, isn't too bad: the modifier <code><span class='Brace'>{</span><span class='Function'>𝔽</span><span class='Brace'>}</span></code> does it, as does <code><span class='Modifier2'>○</span><span class='Function'>⊢</span></code>.</p>
<h3 id="scan-ordering-is-weird">Scan ordering is weird</h3>
<p>Scan moves along the array so that it uses results as left arguments, which is opposite to the usual right-to-left order of evaluation. But I think this is still better than scanning the array in reverse. You can always use Swap on the operand, or recover the APL scan ordering by doing a Reduce-Each on Prefixes.</p>
<h3 id="only-errors-in-functions-can-be-caught">Only errors in functions can be caught</h3>
<p>The modifier <code><span class='Modifier2'>⎊</span></code> allows errors in a function to be caught, but a more natural unit for this is the block (scope, really). However, catching errors shouldn't be common in typical code, in the sense that an application should have only a few instances of <code><span class='Modifier2'>⎊</span></code>. Ordinary testing and control flow should be preferred instead.</p>
<h3 id="special-names-other-than--cant-be-written-as-modifiers">Special names other than 𝕣 can't be written as modifiers</h3>
<p>I decided that it was better to allow <code><span class='Value'>𝕨</span><span class='Modifier2'>_m_</span><span class='Value'>𝕩</span></code> to work with no spaces than to allow <code><span class='Modifier2'>_</span><span class='Value'>𝕩</span></code> to be a modifier, and this rule also helps keep tokenization simple. But to apply <code><span class='Value'>𝕩</span></code> as a modifier you have to give it a different name.</p>
<h3 id="bins-is-inconsistent-with-index-of">Bins is inconsistent with Index of</h3>
<p>In Dyalog APL, Interval Index is identical to Index Of if the left argument has no duplicate cells and every right argument cell intolerantly matches a left argument cell. In BQN they're off by one—Bins is one larger. But all the caveats for the Dyalog relation indicate this might not be so fundamental.</p>
<h3 id="changing-boundary-behavior-can-require-very-different-code">Changing boundary behavior can require very different code</h3>
<p>This mainly applies to pairwise operations; for bigger stencils you'd use Windows, and probably handle boundaries with multidimensional selection. For pairwise operations there are four different paths you might use: decrease size using <code><span class='Function'>↓</span></code>; periodic conditions with <code><span class='Function'>⌽</span></code>; fixed or computed boundaries with <code><span class='Function'>«</span></code> and <code><span class='Function'>»</span></code>; and increased size with <code><span class='Function'>∾</span></code>. Having all this flexibility is great, and it's hard to imagine a parametrized system that offers the same without being difficult to remember. However, some of these functions take lengths and some take values, the latter class only works on one dimension at a time, and for <code><span class='Function'>∾</span></code> the argument can go on either side. This is frustrating if you have a reason to switch between the conditions.</p>
<h3 id="exact-result-of-power-is-unspecified">Exact result of Power is unspecified</h3>
<p>The other arithmetic functions round to nearest, and compound functions such as <code><span class='Value'>⊥</span></code> have been removed. But Power makes no guarantees, and the result could change over time based on different special code. Dyadic logarithm is similar, but expected because of its inverse status.</p>
<h3 id="empty-left-argument-to-select">Empty left argument to Select</h3>
<p>Select chooses whether the left argument maps to right argument axes or selects from the first axis only based on its depth. Without prototypes an empty array has depth 1, so it selects no major cells. However, it could also select from no axes (a no-op) and in some contexts the other behavior would be surprising.</p>
<h3 id="unclear-primitive-names">Unclear primitive names</h3>
<p>Blanket issue for names that I don't find informative: "Solo", "Bins", "Find", and "Group".</p>
<h3 id="strands-go-left-to-right">Strands go left to right</h3>
<p>This is the best ordering, since it's consistent with <code><span class='Bracket'>⟨</span><span class='Separator'>⋄</span><span class='Bracket'>⟩</span></code> lists. And code in a strand probably shouldn't have side effects anyway. Still, it's an odd little tack-on to say separators <em>and strands</em> go left to right, and it complicates the implementation a little.</p>
<h3 id="should-have-a-rounding-function">Should have a rounding function</h3>
<p>There is a standard way to round floats—to nearest integer, ties to even—but it's fairly hard to implement and would have to be specially recognized for performance. It would be nice to have a better way to access this.</p>
<h3 id="primitive-name-capitalization">Primitive name capitalization</h3>
<p>I went with "Index of" and "Less Than or Equal to" but the last word blends into surrounding text. Should they be fully capitalized or hyphenated?</p>
<h2 id="solved-problems">Solved problems</h2>
<p>Problems that existed in mainstream APL or a transitional BQN that have in my opinion been put to rest (while in some cases introducing new problems). Listed in reverse chronological order by time solved, by my recollection.</p>
<h3 id="array-reductions-are-annoying">Array reductions are annoying</h3>
<p>There are really three kinds of reduction a BQN programmer might want to use.</p>
<ul>
<li><code><span class='Function'>𝔽</span><span class='Modifier'>´</span></code> Apply the function between elements of a list (Lisp).</li>
<li><code><span class='Function'>𝔽</span><span class='Modifier'>˝</span></code> Apply it between major cells of an array (SHARP).</li>
<li><code><span class='Function'>𝔽</span><span class='Modifier'>¨˝</span></code> Apply it between elements of an array, enclosing results to get a new array (NARS).</li>
</ul>
<p>BQN bounced between these some at first; eventually I decided it really needed two, with <code><span class='Function'>𝔽</span><span class='Modifier'>˝</span></code> equivalent to <code><span class='Function'>𝔽</span><span class='Modifier'>´</span><span class='Function'><</span><span class='Modifier'>˘</span></code>. The last requires two symbols, but they can always be used together as a unit, so I think this is no longer annoying.</p>
<h3 id="modifier-and-composition-terminology">"Modifier" and "composition" terminology</h3>
<p>1-modifiers and 2-modifiers used to be called "modifiers" and "compositions", respectively, and sometimes "operators" collectively. The new names are much better, although they do leave a disconnect between the names for modifiers, and those for their inputs—"operands".</p>
<h3 id="cant-return-from-inner-functions">Can't return from inner functions</h3>
<p>Fixed by adding block returns such as <code><span class='Value'>label</span><span class='Gets'>←</span></code> to jump out of a block with header name <code><span class='Value'>label</span></code>. Hopefully these don't cause too many new problems.</p>
<p>This was an issue with using functions as control flow. For example, when looping through an array with Each, you can't decide to exit early. In a curly-brace language you would just use a for loop and a return. In BQN, we need… longjmp? Maybe not as crazy as it sounds, and potentially worth it in exchange for replacing control structures.</p>
<h3 id="ambivalent-explicit-functions">Ambivalent explicit functions</h3>
<p>Fixed with multiple bodies: if there are two bodies with no headers such as <code><span class='Brace'>{</span><span class='Number'>2</span><span class='Function'>×</span><span class='Value'>𝕩;𝕨</span><span class='Function'>-</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>, they are the monadic and dyadic case.</p>
<h3 id="how-to-choose-a-partitioning-function">How to choose a partitioning function?</h3>
<p>Fixed with <a href="../doc/group.html">Group</a>, which I found May 2020. Group serves as a much improved <a href="https://aplwiki.com/wiki/Partition">Partition</a>. However, it doesn't partition along multiple axes, so a dedicated partition function that does this could also be wanted. Or could Group be made to work with multiple axes as well as multidimensional indices?</p>
<h3 id="key-doesnt-do-what-you-want">Key doesn't do what you want</h3>
<p>Fixed with <a href="../doc/group.html">Group</a> to my satisfaction, except for the trailing-empty-group problem. There were various issues with Key operators in J and Dyalog, such as the fact that the ordering and presence of groups depends on where and whether the keys appear. Also, Dyalog's Key can return keys and values, but they are in a different format than the input: an array of pairs instead of two arrays. Monadic Group returns indices, which can be used how the programmer wants.</p>
<h3 id="greek-letter-issues">Greek letter issues</h3>
<p>Fixed by not using Greek letters. In particular, the idea of using fancy Latin letters as fixed names for function arguments was suggested in proto-BQN sessions, possibly by Nathan Rogers.</p>
<h3 id="stranding-gotchas">Stranding gotchas</h3>
<p>Fixed with list notation, which descends from the array notation developed by Phil Last and later Adám Brudzewsky. The problem that array notation has much more cluttered syntax than stranding has pretty much been fixed by the ligature character <code><span class='Ligature'>‿</span></code>, which I discovered during proto-BQN discussions.</p>
<h3 id="functions-are-not-first-class">Functions are not first class</h3>
<p>Fixed by allowing a variable to be written with a different syntactic class than it was created with, suggested by Adám in proto-BQN discussions.</p>
<h3 id="apl-is-not-context-free">APL is not context-free</h3>
<p>Fixed with the casing conventions for variable names, which I think I first saw in <a href="https://aplwiki.com/wiki/APL%5Civ">APL\iv</a>, although the cases are swapped relative to BQN.</p>
<h3 id="selective-assignment-requires-a-named-variable">Selective assignment requires a named variable</h3>
<p>Fixed with structural Under, which I developed in 2017 and 2018.</p>
<h3 id="its-hard-use-an-array-as-a-major-cell">It's hard use an array as a major cell</h3>
<p>Fixed with <code><span class='Function'>≍</span></code>: dyadic form from A+ and monadic/dyadic pair from J.</p>
<h3 id="scan-and-windowed-reduce-shouldnt-always-reduce">Scan and Windowed Reduce shouldn't always reduce</h3>
<p>Fixed with Prefix, Suffix, and Infix operators in J. Changed to functions in BQN.</p>
|