aboutsummaryrefslogtreecommitdiff
path: root/docs/commentary/problems.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/commentary/problems.html')
-rw-r--r--docs/commentary/problems.html13
1 files changed, 10 insertions, 3 deletions
diff --git a/docs/commentary/problems.html b/docs/commentary/problems.html
index fbdd6eb5..d42a99b6 100644
--- a/docs/commentary/problems.html
+++ b/docs/commentary/problems.html
@@ -23,6 +23,7 @@
<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>
@@ -60,6 +61,8 @@
<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>
@@ -68,14 +71,16 @@
<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="group-doesnt-include-trailing-empty-groups">Group doesn't include trailing empty groups</h3>
<p>But there are workarounds, described in <a href="../doc/group.html">its documentation</a>. dzaima has suggested allowing a single extra element in the index argument to specify the result shape. Another possibility is for the result prototype to be specified to allow overtaking.</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 &quot;nothing&quot; 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="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 &quot;nothing&quot; 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="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="prefixessuffixes-add-depth-and-windows-doesnt">Prefixes/Suffixes add depth and Windows doesn't</h3>
@@ -91,6 +96,8 @@
<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'>&lt;≑</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>
@@ -115,7 +122,7 @@
<h3 id="inputs-to-modifiers-are-called-operands">Inputs to modifiers are called operands?</h3>
<p>&quot;Operand&quot; is derived from &quot;operator&quot;. &quot;Modificand&quot; 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.</p>
+<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>