diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-09-03 17:23:40 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-09-03 17:23:40 -0400 |
| commit | af948faa3d79ae682d971c71704f9334cf8e847f (patch) | |
| tree | 80e7d540da7ee7b5ca4fbe78457947bedffa4a84 /docs/problems.html | |
| parent | dbaefcd18e98d1cad4609766b82e4e31758a7619 (diff) | |
Closure problem with affine characters
Diffstat (limited to 'docs/problems.html')
| -rw-r--r-- | docs/problems.html | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/docs/problems.html b/docs/problems.html index a1f5dcfb..8b6afb02 100644 --- a/docs/problems.html +++ b/docs/problems.html @@ -12,7 +12,7 @@ <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="control-flow-substitutes-have-awkward-syntax">Control flow substitutes have awkward syntax</h3> -<p>At the moment BQN has no control structures, instead preferring operators, 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. Given that blocks without headers also end up with an unexpected type if you don't use the inputs, it's safe to say BQN isn't great for imperative programming overall. But that's a big loss, and it's very much worth fixing if it can be done with something like a single control structure that conditionally or repeatedly executes an immediate block.</p> +<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. Given that blocks without headers also end up with an unexpected type if you don't use the inputs, it's safe to say BQN isn't great for imperative programming overall. But that's a big loss, and it's very much worth fixing if it can be done with something like a single control structure that conditionally or repeatedly executes an immediate block.</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> @@ -28,7 +28,7 @@ <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="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>).</p> +<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="syntactic-type-erasure">Syntactic type erasure</h3> @@ -82,6 +82,9 @@ <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="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> @@ -105,7 +108,7 @@ <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 operator <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> +<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="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="exact-result-of-power-is-unspecified">Exact result of Power is unspecified</h3> |
