diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-07-18 18:26:52 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-07-18 18:29:59 -0400 |
| commit | 229e2cd2f5c78b13c483a8559dead2c8f31d8e42 (patch) | |
| tree | 9d6a1ff0100bda7632948987352b3d6614c3eeb5 /docs/problems.html | |
| parent | 010b97c8cf346dfeafc289ae66f77e8c61cd9865 (diff) | |
Terminology changes: subject, 1/2-modifier, Box/Unbox to Enclose/Merge, blocks
Diffstat (limited to 'docs/problems.html')
| -rw-r--r-- | docs/problems.html | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/docs/problems.html b/docs/problems.html index 56467ba7..5f053696 100644 --- a/docs/problems.html +++ b/docs/problems.html @@ -5,7 +5,7 @@ <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="control-flow-with-function-selection-has-awkward-syntax">Control flow with function selection has awkward syntax</h3> -<p>At the moment BQN has no control structures, instead preferring function recursion, iteration, and selection. Selection is awkward because the result of selecting from a list of functions must be a value syntactically. It also often doesn't need an argument, since it can refer to values from the containing function because of lexical scoping. There should probably be a function that takes a function argument and invokes it, possible with an empty list as a dummy left argument. Somewhat like the operator <code><span class='Brace'>{</span><span class='Function'>π½</span><span class='Brace'>}</span></code>. But also: should a <code><span class='Brace'>{}</span></code> object that doesn't refer to its arguments be special? Some kind of "block" construct?</p> +<p>At the moment BQN has no control structures, instead preferring function recursion, iteration, and selection. Selection is awkward because the result of selecting from a list of functions is a subject syntactically. It also often doesn't need an argument, since it can refer to values from the containing function because of lexical scoping. There should possibly be a function that takes a function argument and invokes it, possible with an empty list as a dummy left argument. Somewhat like the modifier <code><span class='Brace'>{</span><span class='Function'>π½</span><span class='Brace'>}</span></code>.</p> <p><em>Potentially solved by multiple headers, blocks, and block returns. Needs reevaluation later.</em></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> @@ -14,7 +14,7 @@ <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 unboxed number, you need something like <code><span class='Value'>list</span><span class='Composition'>βΈ</span><span class='Function'>β</span><span class='Composition'>βΎ</span><span class='Function'><</span><span class='Value'>elt</span></code>.</p> +<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> @@ -30,9 +30,9 @@ <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). Not really fixable; too much precedent.</p> <h3 id="can-t-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 comparison 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='Composition'>βΈ</span><span class='Function'>β</span><span class='Composition'>βΎ</span><span class='Function'><</span></code> is TAO <code><span class='Function'>β€</span></code>).</p> +<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="syntactic-type-erasure">Syntactic type erasure</h3> -<p>A programmer can call an operator on either a syntactic function or value, but there's no way to know within the operator 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 array syntax suggest it should be Constant.</p> +<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.</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> @@ -54,22 +54,22 @@ <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="poor-font-support-">Poor font support</h3> -<p>Characters <code><span class='Function'>β₯βΎ</span><span class='Composition'>βββ</span><span class='Modifier'>Λ</span></code> and double-struck letters are either missing from many fonts or drawn strangely.</p> +<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="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='Composition'>β</span><span class='Function'>β£-</span><span class='Number'>1</span><span class='Function'>+β½</span><span class='Composition'>βΈ</span><span class='Function'>β</span></code>.</p> +<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-aren-t-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='Composition'>ββ</span></code> to not be particularly good fits for what they describe.</p> +<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="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='Composition'>β</span><span class='Function'>β’</span><span class='Value'>a</span></code>).</p> +<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-don-t-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='Composition'>β</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> +<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="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="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.</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="converting-a-function-expression-to-a-syntactic-value-is-tricky">Converting a function expression to a syntactic value 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>, 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 value to function, isn't too bad: the operator <code><span class='Brace'>{</span><span class='Function'>π½</span><span class='Brace'>}</span></code> does it.</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>, 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> <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="prefixes-suffixes-add-depth-and-windows-doesn-t">Prefixes/Suffixes add depth and Windows doesn't</h3> @@ -84,7 +84,7 @@ <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 operator, duplicating either the right argument rank or (negated) left argument length. A nested Windows would only require Each.</p> +<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="group-doesn-t-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="scan-ordering-is-weird">Scan ordering is weird</h3> @@ -97,14 +97,14 @@ <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", "Unique Mask", "Find", and "Group".</p> -<h3 id="-modifier--and--composition--terminology">"Modifier" and "composition" terminology</h3> -<p>Since the two have different syntax, it's important that they have completely separate names. "Modifier" is good but "composition" is not, as it doesn't seem to fit with Rank, Depth, or Iterate. There's also often a need for a term that refers to both. I've been using "operator" but that can be confusing.</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="-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="can-t-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> |
