diff options
Diffstat (limited to 'docs/commentary')
| -rw-r--r-- | docs/commentary/bacon.html | 2 | ||||
| -rw-r--r-- | docs/commentary/fanart.html | 2 | ||||
| -rw-r--r-- | docs/commentary/history.html | 28 | ||||
| -rw-r--r-- | docs/commentary/index.html | 2 | ||||
| -rw-r--r-- | docs/commentary/orchard.html | 2 | ||||
| -rw-r--r-- | docs/commentary/primitive.html | 12 | ||||
| -rw-r--r-- | docs/commentary/problems.html | 152 |
7 files changed, 100 insertions, 100 deletions
diff --git a/docs/commentary/bacon.html b/docs/commentary/bacon.html index d2c7ca27..d9af91a9 100644 --- a/docs/commentary/bacon.html +++ b/docs/commentary/bacon.html @@ -4,7 +4,7 @@ <title>BQN: How to cook bacon</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">commentary</a></div> -<h1 id="how-to-cook-bacon">How to cook bacon</h1> +<h1 id="how-to-cook-bacon"><a class="header" href="#how-to-cook-bacon">How to cook bacon</a></h1> <p><em>In BQN, bacon is American, or side, bacon. The method described here works best with medium to thick cuts, and leaves the bacon uniformly cooked and crispy. If you prefer parts of your bacon chewy and underdone, seek help elsewhere.</em></p> <p>Begin with a heated pan at least as wide as the length of the bacon. Prefer cast iron. Cook somewhat hotter than medium, but in order to avoid sticking, don't let the pan reach full heat before starting. However, there is never any need to lubricate the pan, as grease from the cooking bacon will soon serve this purpose.</p> <p>Use metal tongs to hold and move strips of bacon during cooking. Lay three strips of bacon parallel in the center of the pan, and after a minute or two place three at a right angle to these, on top of them. After another few minutes, flip the first strips from the bottom. This is accomplished by pulling each one out from under the top strips by the end, then setting it back on top upside-down with that end on the opposite side of the pan. For more even cooking you might also rotate (<code><span class='Number'>1</span><span class='Modifier2'>⊸</span><span class='Function'>⌽</span></code>) the three strips, so that the center one ends up on one side and one of the side strips ends up in the faster-cooking center.</p> diff --git a/docs/commentary/fanart.html b/docs/commentary/fanart.html index 6b005248..d20de25a 100644 --- a/docs/commentary/fanart.html +++ b/docs/commentary/fanart.html @@ -4,7 +4,7 @@ <title>BQN art</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">commentary</a></div> -<h1 id="bqn-art">BQN art</h1> +<h1 id="bqn-art"><a class="header" href="#bqn-art">BQN art</a></h1> <p><a href="https://codeberg.org/wezl">Wezl</a> has provided a view into the BQN programmer in 𝕩e's typical place of residence.</p> <p><a href="https://ermineii.github.io/paste/#0fZExDoMwDEX3nOKPZPIZWCJ54gA18gWQuvb4dSghjtP2C2XgPcX4k3BHQ9JNCCGSJrSqrhGyl@R6N1H250w3bMD@neph3@lueAaB6lI2uQkUOJPAHm48DjDwqufIqfzMubuvy27XvszVztAnk6p4oypj48yHZubxDywIDiM4yKm13iQphYZZZyWCZe8OCqTPf@RPa6J/Qm8%23DYs7DoMwEAV7n@J1fCQMQenSYeUQlICXZCXYEHuROD4rTTWjWX@iZTHz5@CrqF5YeSOZdjL3Fz8l9XqpBefaGvrlDKNcKgSKiRfCO@0sxIy@6x8OwGZWMkWcEinZQwihGUY8fYe6vQE">Depiction</a>, <a href="https://ermineii.github.io/paste/#0jZA7DsQgDER7TuFyU/kMKUCytsgBMPIFIm27x18gJHxDdoQoeKPBHgVZUktlglCLVYdWkbWDVHg4PXWUyrunG2wAbkxl93MWCZ/GgGEn//NpwIYTMvhDJ28/8OAb7pqjuVXcPbfls6/xiuqKOglFuHZES/FCtMtCtSVOUnkIHj1sDMLAw/ByLjUMBvgYz1q7HEsYp3XYi2UiX4q62nuPlbieSk0jmij4I@k@7gc%23Fcu7CsJAEIXhfp/ikCYXcBODYBFsDD6BlWXcncSBzRg3I0Sf3hVO9R3@icTZVT@B7PgUvfKXcEJ2XDTrzF@K/M7Twltedhg5kAwzJXuJHaJa3TQdxtQV9MEr0gpXoicf2REucWYhZrRNuzcAQlJZyeMtnmJqCH2/O99wsA2q@gc">remodel</a>, <a href="https://ermineii.github.io/paste/#07ZhLbuMwDIavInTVAAV4hmwM/Cujm26qQBco0gFmk@MPqYdFSZbtboJMKsFxYPK3HuRHR87ni1maq5q9Li4yVbM2exfn2blz64aWWRuNrR/6vOKezWzMpeN2Xzxh1cd3rSBZngyfJFQrQOyVD5KkGYY9NzlXApq6LQZCx0@GcHldS7SKGIM4/laLgqpMBPDlTkCdmFdTqWAqlTlxXykXSWbtNFExZAgS614vWWYmtuR5fJ5iKK11G41e3gZqd0aNfAgK1lrUINM1JWstajwPRs0Am6ixm1ErVSuoMWlmmkzJWouakGY0awO1R0WNYgQ0aw1qTFoQFrA1rEFWYR1MwVEDGzuDqsStoQ3pqsCtoS3ApnEbtD0obbTkV@FW0yawRaXGraZNpiEqLwS6uInLy2oua94QhxSdJq4GLvGmiBvA/ffAiWCXN57OEdw8Skdpuw3afh1t4T3ikXHzT8zB21PwRpE39mwChwQcNoFDAg47wIUNIxNHx4ibBnHPQlz4p8TaXeQQkMMOcgjIYR@5sNW70WDu1zHH87X2CHMQ5rDLHI4zJ@0odGYw90TMUQZgBzqkr23matUWcn4Cd0DOUyP3XAuT31hURoqbx2tlK2FLtrNOXk7finFaU0bEUmK1kdaU2DH6pVdG/ydroXQOPpx@q7SYWad5gy9UUDUULdv1@A7gzUzBzMu@5R2YFyOMnzdc0TrLtUPaz6cuQk6R9u9BndIMVbJqxeKmRZzMAYFDIcvGzGiRnIWzwroqLY1OGSklV7HxnZ9TH@X9yUwlmt5KNcTyNGnI5h7FNorgvkXw/oMieB9FMIpg/BKMIhhF8EBFINerhRDCs1oO/qWhVxSO@qUh57lXIaHjTp3w8adbLerOpmb4@NutHN8RjfpZq5/LPw%23PY5NT8MwDIbv/RVWL2kHS8s0CYl@HKiQOMAJLki7ZIlXDKkTNZlE@fWkDGH5ZPl9nndE1jLExaI8OY4v9I3Qgbj1UTSwXgpxpNHTlygbCBiDRzRFLet92WTwN@MKIWacH1@fn1I@b/2MQKYTimlSkRwL@LV0YoVuT2oiu9zBIb/QD/k1TI5d8Eqj6Nsq5fv86t8ACXk8x@gYHGtL@rMT3qqlKEXvwYKCpa0uD32eipNFVhMWwqsQUa4t5EdILVLrLKs2EN8pQNpClzCgmUkjPMwTMRLBrt7drOrkQQ5o4MwG55RBGIbt/RvsZQ2b6gc">animation</a>.</p> <p><em>Links contain the encoded art, which is CC-BY 4.0: see the "setup JS" pane.</em></p> diff --git a/docs/commentary/history.html b/docs/commentary/history.html index d4b01d0b..22197c09 100644 --- a/docs/commentary/history.html +++ b/docs/commentary/history.html @@ -4,14 +4,14 @@ <title>BQN's development history</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">commentary</a></div> -<h1 id="bqns-development-history">BQN's development history</h1> +<h1 id="bqns-development-history"><a class="header" href="#bqns-development-history">BQN's development history</a></h1> <p>I (<a href="https://mlochbaum.github.io/">Marshall Lochbaum</a>) began designing BQN as a "fixed APL" in collaboration with my colleagues at <a href="https://aplwiki.com/wiki/Dyalog_Ltd.">Dyalog</a>, and decided to take it on as a personal project when I chose to leave the company several months later in early 2020. BQN is influenced by my array language background, previous work in programming design, studies of APL history, and design discussions before and after starting work on the language. I developed most of the novel functionality in BQN, and am at the end of the day the one who writes the spec, but it includes significant contributions from collaborators, most notably <a href="https://github.com/dzaima">dzaima</a> and <a href="https://github.com/abrudz">Adám Brudzewsky</a>.</p> -<h3 id="background">Background</h3> +<h3 id="background"><a class="header" href="#background">Background</a></h3> <p>I learned <a href="https://aplwiki.com/wiki/J">J</a> as my first computer programming language in 2009, and it's been my language of choice for personal projects from then until I started working with BQN. My first exposure to APL was <a href="https://aplwiki.com/wiki/Dyalog_APL">Dyalog APL</a>, which I began learning gradually after starting work at Dyalog in 2017; while I understand every primitive in detail (I've substantially reimplemented most of them), I've never written even a medium-sized script with it. I studied APL's history and many other APL dialects while helping to create the new <a href="https://aplwiki.com/wiki/Main_Page">APL Wiki</a> in late 2019. In particular, I found <a href="https://aplwiki.com/wiki/A+">A+</a> to be a very sound design and nominally took it as the starting point for BQN. As a result, BQN draws more from a general concept of APL than any particular dialect.</p> <p>I have been working on programming language design since 2011 or earlier. The start of my first major language, <a href="https://github.com/mlochbaum/ILanguage">I</a>, might be placed in 2012 when I published a paper on its approach to mapping, unifying J's trains and function rank. By this time I had worked with several languages including Python and Factor, and implemented little interpreters in Java, Scala, and Haskell. There are many new ideas in I and some of them have made it to BQN, but the language has served mainly as a warning: its pure and simple syntax and approach to array and tacit programming lead to a rigidity that seems to take over from any human designer. And the end result is not usable. So I sought out constructs that would give back some control, like APL's two-layer function/operator syntax and explicit functions (although Dyalog has lexical scoping, it is crippled by the lack of closures and I ended up learning proper use of lexical scoping from Javascript—I've never done real work with any actual Lisp). Another language that I envisioned before BQN, called Iridescence, goes further in this direction, with Python-like syntax that is "noisy" relative to APL. It remains purely theoretical (I'll implement it some day) but has already had an influence on some BQN primitives.</p> <p>The idea of a "fixed APL" is always percolating in the APL community, because of its long history and strong <a href="https://aplwiki.com/wiki/Backwards_compatibility">backwards compatibility</a> requirements. BQN arose out of sessions by the Young APLers Group (YAG, unfortunately) inside Dyalog after I suggested that wild ideas for the future of APL might be a good topic for meetings (the previous order of business, right at YAG's formation, was creating the APL Wiki). At these meetings <a href="https://github.com/abrudz">Adám</a>, <a href="https://rikedyp.uk/">Richard Park</a>, <a href="https://www.dyalog.com/blog/2019/08/welcome-nathan-rogers/">Nathan Rogers</a>, and sometimes others discussed and proposed many ideas including the sketch I created that ended up as the blueprint of BQN. When I left Dyalog (putting an end to any notions of using those ideas at the company), I joined <a href="https://chat.stackexchange.com/rooms/52405/the-apl-orchard">The APL Orchard</a> forum, which most YAG members already used, to post about BQN. <a href="https://github.com/dzaima">dzaima</a> quickly began building his own BQN implementation using the existing dzaima/APL, and has discussed and contributed to most BQN design decisions since.</p> <p><a href="https://shapecatcher.com/index.html">Shapecatcher</a> is an essential resource for finding appropriate unicode characters. I've been using it heavily, and so has everyone else interested in glyph choices.</p> -<h2 id="timeline">Timeline</h2> +<h2 id="timeline"><a class="header" href="#timeline">Timeline</a></h2> <p>The table documents when I encountered features or interesting decisions in BQN. The "source" field indicates how I became aware of the idea while the "person" field gives, to the best of my knowledge, the original inventor (in blank entries and those that start with "w/", I am an inventor).</p> <table> <thead> @@ -201,26 +201,26 @@ </tr> </tbody> </table> -<h2 id="features">Features</h2> +<h2 id="features"><a class="header" href="#features">Features</a></h2> <p>Discussion of specific features from the timeline above, with more detail.</p> -<h4 id="structural-under">Structural Under</h4> +<h4 id="structural-under"><a class="header" href="#structural-under">Structural Under</a></h4> <p>I developed structural Under in 2017 and 2018. By <a href="https://aplwiki.com/wiki/Dyalog_user_meeting#Dyalog_.2717">Dyalog '17</a> I had figured out the basic concept, and sometime later I discovered it could be unified with J's Under operator, which was being considered for inclusion in Dyalog.</p> -<h4 id="prefix-suffix-and-windows">Prefix, Suffix, and Windows</h4> +<h4 id="prefix-suffix-and-windows"><a class="header" href="#prefix-suffix-and-windows">Prefix, Suffix, and Windows</a></h4> <p>I discovered Prefix, Suffix, and Windows while thinking about Iridescence, probably in 2019. They are influenced by J's Prefix, Suffix, and Infix operators, but in Iridescence, with no distinction between functions and arrays, Prefix is just the Take function, and Suffix is Drop!</p> -<h4 id="array-notation">Array notation</h4> +<h4 id="array-notation"><a class="header" href="#array-notation">Array notation</a></h4> <p>APL <a href="https://aplwiki.com/wiki/Array_notation">array notation</a> has been developed mainly by Phil Last and later Adám Brudzewsky. The big difference from array literals in other languages is the idea that newline should be a separator equivalent to <code><span class='Separator'>⋄</span></code>, as it is in ordinary APL execution including dfns. The changes I made for BQN, other than the ligature <code><span class='Ligature'>‿</span></code> discussed below, were to use dedicated bracket pairs <code><span class='Bracket'>⟨⟩</span></code> and <code><span class='Value'>[]</span></code>, and to allow <code><span class='Separator'>,</span></code> as a separator.</p> <p>I picked out the ligature character <code><span class='Ligature'>‿</span></code> between YAG meetings, but I think Richard Park was most responsible for the idea of a "shortcut" list notation.</p> -<h4 id="double-struck-special-names">Double-struck special names</h4> +<h4 id="double-struck-special-names"><a class="header" href="#double-struck-special-names">Double-struck special names</a></h4> <p>There was a lot of discussion about names for arguments at YAG (no one liked alpha and omega); I think Nathan Rogers suggested using Unicode's mathematical variants of latin letters and I picked out the double-struck ones. My impression is that we were approaching a general concensus that "w" and "x" were the best of several bad choices of argument letters, but that I was the first to commit to them.</p> -<h4 id="assert-primitive">Assert primitive</h4> +<h4 id="assert-primitive"><a class="header" href="#assert-primitive">Assert primitive</a></h4> <p>Nathan Rogers suggested that assertion should be made a primitive to elevate it to a basic part of the language. I used J's <code><span class='Value'>assert</span></code> often enough for this idea to make sense immediately, but I think it was new to me. He suggested the dagger character; I changed this to the somewhat similar-looking <code><span class='Function'>!</span></code>. The error-trapping modifier <code><span class='Modifier2'>⎊</span></code> is identical to J's <code><span class='Value'>::</span></code>, but J only has the function <code><span class='Value'>[:</span></code> to unconditionally throw an error, with no way to set a message.</p> -<h4 id="context-free-grammar">Context-free grammar</h4> +<h4 id="context-free-grammar"><a class="header" href="#context-free-grammar">Context-free grammar</a></h4> <p>In YAG meetings, I suggested adopting <a href="https://aplwiki.com/wiki/APL%5Civ">APL\iv</a>'s convention that variable case must match variable type in order to achieve a context-free grammar. Adám, a proponent of case-insensitive names, pointed out that the case might indicate the type the programmer wanted to use instead of the value's type, creating cross roles.</p> -<h4 id="headers">Headers</h4> +<h4 id="headers"><a class="header" href="#headers">Headers</a></h4> <p>The idea of dfn headers is very common in the APL community, to the extent that it's hard to say which proposals lead to the form now used in BQN. A+ has headers which are similar but go outside the braces, and BQN headers aren't all that different from tradfn headers either. I found when creating BQN2NGN that ngn/apl allows dfns to include a monadic and dyadic case, separated by a semicolon. Some time later I realized that the ability to include multiple bodies is very powerful with headers because it enables a primitive sort of pattern matching, something I already wanted to squeeze into the language. I discussed this with dzaima, who added header support to dzaima/BQN almost immediately and was thus able to investigate the details of the format.</p> -<h4 id="group">Group</h4> +<h4 id="group"><a class="header" href="#group">Group</a></h4> <p>I've been fiddling with the idea of function or map inversion (preimage creation, really) for several years, and in fact independently discovered something very similar to K's Group function <code><span class='Function'>=</span></code>, which is an excellent tool for languages that have dictionaries. I liked this approach as it didn't have all the ordering issues that J's Key has. However, I also didn't really want to introduce dictionaries to BQN, as they have a very strange relation to multidimensional arrays—are arrays like dictionaries with multiple keys, or dictionaries with a single vector key? I've been a proponent of <code><span class='Function'>/</span><span class='Modifier'>⁼</span></code> as a programming tool for <a href="http://www.jsoftware.com/pipermail/programming/2010-September/020302.html">much longer</a>. I'd also developed a sophisticated view of <a href="https://aplwiki.com/wiki/Partition_representations">partition representations</a> while studying an extension to Dyalog's Partitioned Enclose proposed by Adám and included in Dyalog 18.0. I finally put all this together while fighting with Key to develop BQN's compiler: I realized that if the "key" argument was restricted to array indices, then it would make sense for the result to be an array, and that this was simply the "target indices" partition representation minus the requirement that those indices be nondecreasing.</p> -<h4 id="before--and-after-">Before <code><span class='Modifier2'>⊸</span></code> and After <code><span class='Modifier2'>⟜</span></code></h4> +<h4 id="before--and-after-"><a class="header" href="#before--and-after-">Before <code><span class='Modifier2'>⊸</span></code> and After <code><span class='Modifier2'>⟜</span></code></a></h4> <p>It happens that BQN's Before (<code><span class='Modifier2'>⊸</span></code>) and After (<code><span class='Modifier2'>⟜</span></code>) modifiers are identical to I's hook (<code><span class='Value'>h</span></code>) and backhook (<code><span class='Function'>H</span></code>), but it took some time to arrive at this point. The hook function in I comes from J's 2-train, also called hook (I had probably seen Roger Hui's <a href="https://code.jsoftware.com/wiki/Essays/Hook_Conjunction%3F">remarks</a> that he would prefer hook to be a conjunction, with 2-trains indicating composition instead, but I don't think Roger has proposed a reverse hook). But the model for Before and After was initially APL's Compose (<code><span class='Modifier2'>∘</span></code>) and the complement <a href="https://aplwiki.com/wiki/Reverse_Compose">Reverse Compose</a> that Adám created for Extended Dyalog APL. I noticed the similarity to Bind and decided to unify Binds and Composes at around the same time that I picked the symbols <code><span class='Modifier2'>⊸⟜</span></code>. However, I kept the idea that the one-argument case should be simple composition unless the bound operand had a subject role. Eventually I decided the violation of <a href="problems.html#syntactic-type-erasure">syntactic type erasure</a> was too inconsistent and settled on the current definition. Now I think these forms are better even ignoring constant functions, although I do occasionally run into cases where I'd like to use APL's Compose.</p> -<h4 id="constant-modifier">Constant modifier</h4> +<h4 id="constant-modifier"><a class="header" href="#constant-modifier">Constant modifier</a></h4> <p>The idea of a constant function is nothing new; I named it <code><span class='Value'>k</span></code> in I, taking influence from the <a href="https://en.wikipedia.org/wiki/SKI_combinator_calculus">SKI</a> calculus. It was actually Adám who suggested adding it to Dyalog with the glyph <code><span class='Value'>⍨</span></code>, although I was the one who campaigned for it and introduced it to the public in version 18.0. It wasn't initially clear that a dedicated modifier was needed in BQN because the treatment of data types as constant functions seems to fill this role, but I eventually found that I needed a constant function returning a function too often to leave it out.</p> diff --git a/docs/commentary/index.html b/docs/commentary/index.html index c85c41fe..f5f3d2e0 100644 --- a/docs/commentary/index.html +++ b/docs/commentary/index.html @@ -4,7 +4,7 @@ <title>BQN commentary</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a></div> -<h1 id="bqn-commentary">BQN commentary</h1> +<h1 id="bqn-commentary"><a class="header" href="#bqn-commentary">BQN commentary</a></h1> <p>Documents in this directory give context on how BQN was designed or remark on aspects of the language.</p> <ul> <li><a href="problems.html">Problems with BQN</a></li> diff --git a/docs/commentary/orchard.html b/docs/commentary/orchard.html index 12b5b9a9..0f2aaf42 100644 --- a/docs/commentary/orchard.html +++ b/docs/commentary/orchard.html @@ -4,7 +4,7 @@ <title>BQN: The APL Orchard</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">commentary</a></div> -<h1 id="the-apl-orchard">The APL Orchard</h1> +<h1 id="the-apl-orchard"><a class="header" href="#the-apl-orchard">The APL Orchard</a></h1> <p>BQN users have largely moved to Matrix or Discord chat, and I no longer recommend using the APL Orchard (perhaps also known by the shortcut URL apl.chat). Chat options are discussed <a href="../index.html#where-can-i-find-bqn-users">in the README</a>; this page gives the reasons we switched forums.</p> <p>StackExchange chat requires a StackExchange account with enough reputation, or moderator-granted permissions, to talk, and sets a reputation threshold for some minor features within the chat as well. Those who don't use StackExchange have to make an account and send an email to get permission. While this filtering probably leads to a more dedicated forum base, it does this at the expense of keeping out a lot of people, including many who have a lot to contribute. I think this isn't a good tradeoff, and this seems to be the community concensus as well.</p> <p>StackExchange is not built for bots, and existing tooling for it is not very good. At the time of writing the bot that used to link the APL Orchard to IRC #apl is able to write but not read posts, so that the link only runs one way.</p> diff --git a/docs/commentary/primitive.html b/docs/commentary/primitive.html index fbbd4d5d..87ef3a21 100644 --- a/docs/commentary/primitive.html +++ b/docs/commentary/primitive.html @@ -4,9 +4,9 @@ <title>BQN: What is a primitive?</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">commentary</a></div> -<h1 id="what-is-a-primitive">What is a primitive?</h1> +<h1 id="what-is-a-primitive"><a class="header" href="#what-is-a-primitive">What is a primitive?</a></h1> <p>People sometimes wonder how the set of primitives in BQN was chosen. Outsiders to array programming might assume that the "big idea" of APL is just to take the most common tasks and write them with symbols instead of names—even Dijkstra said something like this, calling APL a "bag of tricks"! I don't think this is quite right, so I'd like to explain my personal view on why it makes sense to call a few special operations "primitives" and give them dedicated symbols. While I think this overlaps some with the ideas of other array designers, I am speaking only for myself here.</p> -<h2 id="names-versus-symbols">Names versus symbols</h2> +<h2 id="names-versus-symbols"><a class="header" href="#names-versus-symbols">Names versus symbols</a></h2> <p>Much of this text will be about why various functions <em>shouldn't</em> be considered primitives, so it makes sense to start with a discussion of the disadvantages of symbols and why we wouldn't want everything to use them.</p> <ul> <li>Words convey meaning more precisely</li> @@ -16,11 +16,11 @@ </ul> <p>A broad theme is that words—that is, language rather than notation—offer more possibilities and shades of meaning. If there are two related concepts, it's often possible to give them names that make both the relation and the difference clear (say, <code><span class='Function'>KeepBefore</span></code> and <code><span class='Function'>KeepUpTo</span></code>). With symbols this is more difficult: only a few broad relations like mirror reflection (which is error prone!) and juxtaposition are usable. But nuanced words can also be a liability. If there is really only one possibility, then a well-chosen symbol might indicate it better and be easier to remember.</p> <p>In BQN, syntactic role is also a factor. Letter casing and underscores allow any word to be written with any role, while a primitive has a fixed role. If a value might be either called as a function or passed as an argument, this will be easier if it's named.</p> -<h2 id="primitive-philosophy">Primitive philosophy</h2> +<h2 id="primitive-philosophy"><a class="header" href="#primitive-philosophy">Primitive philosophy</a></h2> <p>Is language design a process of discovery or invention? A bit of both, of course, but I think primitive design should be mostly discovery. That is, if a function feels invented—or worse, engineered—it's not a good fit for a BQN primitive. Discovery means that the thing in question is in some sense external to the person who describes it, so that if two different people discover something then it will be the exact same thing. An invented thing will always bear marks of its inventor, from the little decisions that could have been made differently.</p> <p>It's not always so clear cut, and there's a little irony in that the <em>collection</em> of all the primitives in a language is definitely engineered. While I think it's a good idea to give symbols to things that are more primitive-like and words to things that are less primitive-like, this leaves room to use symbols relatively more as in APL, or words more as in Python, to focus on different functionality to provide, or to select different primitives when there are a few that provide similar functionality.</p> <p>I do think some acts of engineering are okay, if the purpose is only to make the underlying primitive functionality more accessible. For example, Range (<code><span class='Function'>↕</span></code>) combines two primitive functions with disjoint domains, and Rank (<code><span class='Modifier2'>⎉</span></code>) sticks a few numbers into an arbitrarily-ordered list. I still view these as a little unfortunate, but acceptable for added convenience.</p> -<h2 id="primitive-practice">Primitive practice</h2> +<h2 id="primitive-practice"><a class="header" href="#primitive-practice">Primitive practice</a></h2> <p>Are there primitives out there waiting to be discovered? I think so: fundamental concepts like addition, mapping, or joining one list to another would be reinvented by any society that could develop programming, and would have exactly the same meaning. But this is sort of a vague assertion, and I have no intention of getting into the question of whether anything "actually" exists. A more practical approach is to start with some properties that I associate with high-quality tools of thought:</p> <ul> <li>Simple mathematical description (or better, more than one)</li> @@ -38,7 +38,7 @@ <li>Relationships between primitives can be used in proofs</li> </ul> <p>Again, some properties seem intuitively connected to the ones above but for others the connection isn't so obvious. They are broad patterns that I've observed over years of programming and designing.</p> -<h2 id="arithmetic-primitives">Arithmetic primitives</h2> +<h2 id="arithmetic-primitives"><a class="header" href="#arithmetic-primitives">Arithmetic primitives</a></h2> <p>I can point out that there is already a class of functions that anyone would agree fit the description above, which are the arithmetic functions <code><span class='Function'>+-×÷</span></code>. They are indispensable tools, and it's interesting to note that they are also represented with symbols (not necessarily the same ones) in nearly every language.</p> <p>Why is it that a function as broadly useful as addition should exist at all? It's one example of mathematics (and even if you don't consider programming to be mathematics, it can certainly be described by mathematics) being more structured than direct reasoning can explain. This happens because math imposes structure on itself, as facts about one mathematical object can constrain the behavior of another. The structure might manifest as theorems mathematicians can prove, theorems they can't, or the fuzzier ideas sometimes called "folk theorems". A good illustration is <a href="https://en.wikipedia.org/wiki/Ulam%27s_spiral">Ulam's spiral</a>, the tendency of prime numbers to follow arithmetic patterns. There are a few proofs about specific patterns, and conjectures about others. The broader folk theorem that primes will show patterns in <em>any</em> simple arithmetic arrangement is too vague to even prove, but has lots of supporting evidence and is of practical use to mathematicians working in the field.</p> <svg viewBox='-192.8 -64.8 688 208'> @@ -71,7 +71,7 @@ <p>Folk theorems are a lot like design patterns in programming, in that they can guide or describe an implementation but don't appear in the code directly. A primitive, in contrast, is a precisely specified operation, so it can be used for both organization and in the actual code.</p> <p>Primitives obey mathematical rules—for example that subtraction undoes addition. A sequence of primitives can be manipulated algebraically using these rules, changing it to a different sequence that does the same computation. Symbols are a good fit for algebraic manipulation because the lower overhead required to read them makes it easier to recognize groups of symbols and move them around. The programmer still has to choose what changes to make, but primitive symbols make it easier to perform them correctly.</p> -<h2 id="programming-with-primitives">Programming with primitives</h2> +<h2 id="programming-with-primitives"><a class="header" href="#programming-with-primitives">Programming with primitives</a></h2> <p>APL adds a few arithmetic primitives that aren't common in other languages, but its main contribution is array primitives. Some later APL-family languages including BQN also add combinators—tacit primitives for working with functions (mathematics does have the composition <code><span class='Modifier2'>∘</span></code>; the difference is that APL's combinators are for functions of one or two arguments).</p> <p>The main reason for the three domains of arithmetic, functions, and arrays is simply that these are the main types used for computations in BQN. It might be interesting to note that there are no namespace primitives. In BQN namespaces are used for code organization, not computation. Something similar happens with arrays in C: they aren't the object of computation, so while there are operators for working with pointers (addition, referencing and dereferencing), there aren't any for arrays. One step that makes BQN arrays more suitable to have primitives defined on them is that they are immutable.</p> <p>These days many popular langauges have standard functions or methods for working with arrays, like concatenation, reversal, and mapping. But they're usually treated more as utilities than primitives, and in some cases have extra functionality tacked on that makes them more complicated and less composable (for example Javascript's mapping passes extra arguments to the operand).</p> diff --git a/docs/commentary/problems.html b/docs/commentary/problems.html index 8647bd09..c6da5787 100644 --- a/docs/commentary/problems.html +++ b/docs/commentary/problems.html @@ -4,35 +4,35 @@ <title>Problems with BQN</title> </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">commentary</a></div> -<h1 id="problems-with-bqn">Problems with BQN</h1> +<h1 id="problems-with-bqn"><a class="header" href="#problems-with-bqn">Problems with BQN</a></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> +<h3 id="empty-arrays-lose-type-information"><a class="header" href="#empty-arrays-lose-type-information">Empty arrays lose type information</a></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> +<h3 id="incoherent-monad-dyad-builtin-pairs"><a class="header" href="#incoherent-monad-dyad-builtin-pairs">Incoherent monad-dyad builtin pairs</a></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> +<h3 id="glyphs-are-hard-to-type"><a class="header" href="#glyphs-are-hard-to-type">Glyphs are hard to type</a></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="syntactic-type-erasure">Syntactic type erasure</h3> +<h3 id="syntactic-type-erasure"><a class="header" href="#syntactic-type-erasure">Syntactic type erasure</a></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="control-flow-substitutes-have-awkward-syntax">Control flow substitutes have awkward syntax</h3> +<h3 id="control-flow-substitutes-have-awkward-syntax"><a class="header" href="#control-flow-substitutes-have-awkward-syntax">Control flow substitutes have awkward syntax</a></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="search-function-depth">Search function depth</h3> +<h3 id="search-function-depth"><a class="header" href="#search-function-depth">Search function depth</a></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="right-to-left-multi-line-functions-go-upwards">Right-to-left multi-line functions go upwards</h3> +<h3 id="right-to-left-multi-line-functions-go-upwards"><a class="header" href="#right-to-left-multi-line-functions-go-upwards">Right-to-left multi-line functions go upwards</a></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="tacit-and-one-line-functions-are-hard-to-debug">Tacit and one-line functions are hard to debug</h3> +<h3 id="tacit-and-one-line-functions-are-hard-to-debug"><a class="header" href="#tacit-and-one-line-functions-are-hard-to-debug">Tacit and one-line functions are hard to debug</a></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="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> +<h3 id="hard-to-search-part-of-an-array-or-in-a-different-order"><a class="header" href="#hard-to-search-part-of-an-array-or-in-a-different-order">Hard to search part of an array or in a different order</a></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> +<h3 id="subtraction-division-and-span-are-backwards"><a class="header" href="#subtraction-division-and-span-are-backwards">Subtraction, division, and span are backwards</a></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> +<h3 id="nothing--interacts-strangely-with-before-and-after"><a class="header" href="#nothing--interacts-strangely-with-before-and-after">Nothing (<code><span class='Nothing'>·</span></code>) interacts strangely with Before and After</a></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> +<h3 id="cant-access-array-ordering-directly"><a class="header" href="#cant-access-array-ordering-directly">Can't access array ordering directly</a></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> +<h3 id="comparison-tolerance"><a class="header" href="#comparison-tolerance">Comparison tolerance</a></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> @@ -50,112 +50,112 @@ </tr> </tbody> </table> -<h3 id="no-access-to-fast-high-precision-sum">No access to fast high-precision sum</h3> +<h3 id="no-access-to-fast-high-precision-sum"><a class="header" href="#no-access-to-fast-high-precision-sum">No access to fast high-precision sum</a></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> +<h3 id="assert-has-no-way-to-compute-the-error-message"><a class="header" href="#assert-has-no-way-to-compute-the-error-message">Assert has no way to compute the error message</a></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> +<h3 id="high-rank-array-notation"><a class="header" href="#high-rank-array-notation">High-rank array notation</a></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> +<h3 id="list-splicing-is-fiddly"><a class="header" href="#list-splicing-is-fiddly">List splicing is fiddly</a></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> +<h3 id="cant-always-transfer-ambivalence-in-tacit-code"><a class="header" href="#cant-always-transfer-ambivalence-in-tacit-code">Can't always transfer ambivalence in tacit code</a></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> +<h3 id="poor-font-support-"><a class="header" href="#poor-font-support-">Poor font support</a></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> +<h3 id="choose-and-repeat-have-order-swapped"><a class="header" href="#choose-and-repeat-have-order-swapped">Choose and Repeat have order swapped</a></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> +<h3 id="index-of-privileges-the-first-match"><a class="header" href="#index-of-privileges-the-first-match">Index Of privileges the first match</a></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> +<h3 id="glyphs-that-arent-great"><a class="header" href="#glyphs-that-arent-great">Glyphs that aren't great</a></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> +<h3 id="cant-mix-define-and-modify-in-multiple-assignment"><a class="header" href="#cant-mix-define-and-modify-in-multiple-assignment">Can't mix define and modify in multiple assignment</a></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> +<h3 id="trains-dont-like-monads"><a class="header" href="#trains-dont-like-monads">Trains don't like monads</a></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> +<h3 id="underbind-combination-is-awkward"><a class="header" href="#underbind-combination-is-awkward">Under/bind combination is awkward</a></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> +<h3 id="axis-ordering-is-big-endian"><a class="header" href="#axis-ordering-is-big-endian">Axis ordering is big-endian</a></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> +<h3 id="inverse-is-not-fully-specified"><a class="header" href="#inverse-is-not-fully-specified">Inverse is not fully specified</a></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> +<h3 id="group-doesnt-include-trailing-empty-groups"><a class="header" href="#group-doesnt-include-trailing-empty-groups">Group doesn't include trailing empty groups</a></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> +<h3 id="prefixessuffixes-add-depth-and-windows-doesnt"><a class="header" href="#prefixessuffixes-add-depth-and-windows-doesnt">Prefixes/Suffixes add depth and Windows doesn't</a></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> +<h3 id="deshape-and-reshape-cant-ignore-trailing-axes"><a class="header" href="#deshape-and-reshape-cant-ignore-trailing-axes">Deshape and Reshape can't ignore trailing axes</a></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> +<h3 id="at-which-scope-does-a-block-function-belong"><a class="header" href="#at-which-scope-does-a-block-function-belong">At which scope does a block function belong?</a></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="negative-indices-dont-fail-by-default">Negative indices don't fail by default</h3> +<h3 id="negative-indices-dont-fail-by-default"><a class="header" href="#negative-indices-dont-fail-by-default">Negative indices don't fail by default</a></h3> <p>The typical case when selecting from an array is that a negative index doesn't make sense, and you'd prefer it to give an error. But negative indices are pretty useful in some contexts so BQN trades safety for convenience. Manually checking that indices are non-negative is easier than full range checking, but the issue is that you have to do it manually at all.</p> -<h3 id="rankdepth-negative-zero">Rank/Depth negative zero</h3> +<h3 id="rankdepth-negative-zero"><a class="header" href="#rankdepth-negative-zero">Rank/Depth negative zero</a></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> +<h3 id="tacit-code-cant-build-lists-easily"><a class="header" href="#tacit-code-cant-build-lists-easily">Tacit code can't build lists easily</a></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> +<h3 id="must-read-the-body-to-find-headerless-blocks-type"><a class="header" href="#must-read-the-body-to-find-headerless-blocks-type">Must read the body to find headerless block's type</a></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> +<h3 id="no-one-right-way-to-check-if-a-value-is-an-array"><a class="header" href="#no-one-right-way-to-check-if-a-value-is-an-array">No one right way to check if a value is an array</a></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> +<h3 id="each-block-body-has-its-own-label"><a class="header" href="#each-block-body-has-its-own-label">Each block body has its own label</a></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> +<h3 id="have-to-be-careful-about-intermediate-results-with-affine-characters"><a class="header" href="#have-to-be-careful-about-intermediate-results-with-affine-characters">Have to be careful about intermediate results with affine characters</a></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> +<h3 id="monadic-argument-corresponds-to-left-for--and-"><a class="header" href="#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></a></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> +<h3 id="hard-to-manipulate-the-result-of-a-modifier"><a class="header" href="#hard-to-manipulate-the-result-of-a-modifier">Hard to manipulate the result of a modifier</a></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> +<h3 id="monadic--versus-"><a class="header" href="#monadic--versus-">Monadic <code><span class='Function'>⊑</span></code> versus <code><span class='Function'>></span></code></a></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> +<h3 id="cant-take-prefixes-or-suffixes-on-multiple-axes"><a class="header" href="#cant-take-prefixes-or-suffixes-on-multiple-axes">Can't take Prefixes or Suffixes on multiple axes</a></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> +<h3 id="modified-assignment-modifies-the-left-secondary-argument"><a class="header" href="#modified-assignment-modifies-the-left-secondary-argument">Modified assignment modifies the left (secondary) argument</a></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> +<h3 id="andormaxmin-are-all-tangled-up"><a class="header" href="#andormaxmin-are-all-tangled-up">And/Or/Max/Min are all tangled up</a></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> +<h3 id="acting-on-windows-can-be-awkward"><a class="header" href="#acting-on-windows-can-be-awkward">Acting on windows can be awkward</a></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> +<h3 id="inputs-to-modifiers-are-called-operands"><a class="header" href="#inputs-to-modifiers-are-called-operands">Inputs to modifiers are called operands?</a></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> +<h3 id="converting-a-function-expression-to-a-subject-is-tricky"><a class="header" href="#converting-a-function-expression-to-a-subject-is-tricky">Converting a function expression to a subject is tricky</a></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> +<h3 id="scan-ordering-is-weird"><a class="header" href="#scan-ordering-is-weird">Scan ordering is weird</a></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> +<h3 id="only-errors-in-functions-can-be-caught"><a class="header" href="#only-errors-in-functions-can-be-caught">Only errors in functions can be caught</a></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> +<h3 id="special-names-other-than--cant-be-written-as-modifiers"><a class="header" href="#special-names-other-than--cant-be-written-as-modifiers">Special names other than 𝕣 can't be written as modifiers</a></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> +<h3 id="bins-is-inconsistent-with-index-of"><a class="header" href="#bins-is-inconsistent-with-index-of">Bins is inconsistent with Index of</a></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> +<h3 id="changing-boundary-behavior-can-require-very-different-code"><a class="header" href="#changing-boundary-behavior-can-require-very-different-code">Changing boundary behavior can require very different code</a></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> +<h3 id="exact-result-of-power-is-unspecified"><a class="header" href="#exact-result-of-power-is-unspecified">Exact result of Power is unspecified</a></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> +<h3 id="empty-left-argument-to-select"><a class="header" href="#empty-left-argument-to-select">Empty left argument to Select</a></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> +<h3 id="unclear-primitive-names"><a class="header" href="#unclear-primitive-names">Unclear primitive names</a></h3> <p>Blanket issue for names that I don't find informative: "Solo", "Bins", "Find", and "Group".</p> -<h3 id="modifiers-look-looser-than-trains-without-spaces">Modifiers look looser than trains without spaces</h3> +<h3 id="modifiers-look-looser-than-trains-without-spaces"><a class="header" href="#modifiers-look-looser-than-trains-without-spaces">Modifiers look looser than trains without spaces</a></h3> <p>Consider <code><span class='Function'>⋆</span><span class='Modifier2'>∘</span><span class='Function'>-×</span><span class='Modifier'>˜</span></code>. It's just a sequence of three functions so the use of <code><span class='Modifier2'>∘</span></code> rather than <code><span class='Nothing'>·</span></code> is to highlight structure: <code><span class='Function'>⋆</span><span class='Modifier2'>∘</span><span class='Function'>-</span></code> is more tightly bound so the suggestion is to consider this composition as a single entity. But in fact <code><span class='Function'>-</span></code> is closer to <code><span class='Function'>×</span><span class='Modifier'>˜</span></code> than to <code><span class='Function'>⋆</span></code>, intuitively suggesting the opposite. Adding a space fixes it: <code><span class='Function'>⋆</span><span class='Modifier2'>∘</span><span class='Function'>-</span> <span class='Function'>×</span><span class='Modifier'>˜</span></code> visually connects <code><span class='Function'>⋆</span><span class='Modifier2'>∘</span><span class='Function'>-</span></code>. It's unfortunate that this is something the writer must do rather than something the notation encourages.</p> -<h3 id="tacit-exports-can-leak-data">Tacit exports can leak data</h3> +<h3 id="tacit-exports-can-leak-data"><a class="header" href="#tacit-exports-can-leak-data">Tacit exports can leak data</a></h3> <p>One of the nice facets of BQN's module system is that it provides perfect encapsulation: if you have variables <code><span class='Value'>a</span></code> and <code><span class='Value'>b</span></code> in a namespace (or closure) initialized so that <code><span class='Value'>a</span><span class='Function'>≤</span><span class='Value'>b</span></code>, and all exported operations maintain the property that <code><span class='Value'>a</span><span class='Function'>≤</span><span class='Value'>b</span></code>, then that property will always be true. Well, not quite: if you define, say <code><span class='Function'>Inc</span> <span class='Gets'>⇐</span> <span class='Function'>IncA</span> <span class='Function'>⊣</span> <span class='Function'>IncB</span></code> to increase the values of both <code><span class='Value'>a</span></code> and <code><span class='Value'>b</span></code> by <code><span class='Value'>𝕩</span></code>, then <code><span class='Function'>Inc</span></code> maintains <code><span class='Value'>a</span><span class='Function'>≤</span><span class='Value'>b</span></code>, but <code><span class='Function'>IncA</span></code> doesn't—and it can be extracted with <code><span class='Function'>•Decompose</span></code>. This isn't too serious because it sounds impossible to do accidentally, and it's easy to protect against.</p> -<h3 id="strands-go-left-to-right">Strands go left to right</h3> +<h3 id="strands-go-left-to-right"><a class="header" href="#strands-go-left-to-right">Strands go left to right</a></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="primitive-name-capitalization">Primitive name capitalization</h3> +<h3 id="primitive-name-capitalization"><a class="header" href="#primitive-name-capitalization">Primitive name capitalization</a></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> +<h2 id="solved-problems"><a class="header" href="#solved-problems">Solved problems</a></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="trigonometry">Trigonometry</h3> +<h3 id="trigonometry"><a class="header" href="#trigonometry">Trigonometry</a></h3> <p>Solved with namespaces. dzaima/BQN uses <code><span class='Value'>•math</span></code> to expose math functions, but it could also be provided in a system library (still deciding). It's up to the implementation how the functions are implemented.</p> <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="should-have-a-rounding-function">Should have a rounding function</h3> +<h3 id="should-have-a-rounding-function"><a class="header" href="#should-have-a-rounding-function">Should have a rounding function</a></h3> <p>Also placed in the math namespace.</p> <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="array-reductions-are-annoying">Array reductions are annoying</h3> +<h3 id="array-reductions-are-annoying"><a class="header" href="#array-reductions-are-annoying">Array reductions are annoying</a></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> @@ -163,28 +163,28 @@ <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> +<h3 id="modifier-and-composition-terminology"><a class="header" href="#modifier-and-composition-terminology">"Modifier" and "composition" terminology</a></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> +<h3 id="cant-return-from-inner-functions"><a class="header" href="#cant-return-from-inner-functions">Can't return from inner functions</a></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> +<h3 id="ambivalent-explicit-functions"><a class="header" href="#ambivalent-explicit-functions">Ambivalent explicit functions</a></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> +<h3 id="how-to-choose-a-partitioning-function"><a class="header" href="#how-to-choose-a-partitioning-function">How to choose a partitioning function?</a></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>. Later extended to multiple axes as well to get all the functionality.</p> -<h3 id="key-doesnt-do-what-you-want">Key doesn't do what you want</h3> +<h3 id="key-doesnt-do-what-you-want"><a class="header" href="#key-doesnt-do-what-you-want">Key doesn't do what you want</a></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> +<h3 id="greek-letter-issues"><a class="header" href="#greek-letter-issues">Greek letter issues</a></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> +<h3 id="stranding-gotchas"><a class="header" href="#stranding-gotchas">Stranding gotchas</a></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> +<h3 id="functions-are-not-first-class"><a class="header" href="#functions-are-not-first-class">Functions are not first class</a></h3> <p>Fixed by allowing a variable to be written with a different syntactic role 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> +<h3 id="apl-is-not-context-free"><a class="header" href="#apl-is-not-context-free">APL is not context-free</a></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> +<h3 id="selective-assignment-requires-a-named-variable"><a class="header" href="#selective-assignment-requires-a-named-variable">Selective assignment requires a named variable</a></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> +<h3 id="its-hard-use-an-array-as-a-major-cell"><a class="header" href="#its-hard-use-an-array-as-a-major-cell">It's hard use an array as a major cell</a></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> +<h3 id="scan-and-windowed-reduce-shouldnt-always-reduce"><a class="header" href="#scan-and-windowed-reduce-shouldnt-always-reduce">Scan and Windowed Reduce shouldn't always reduce</a></h3> <p>Fixed with Prefix, Suffix, and Infix operators in J. Changed to functions in BQN.</p> |
