diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-13 13:20:34 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-13 13:20:34 -0400 |
| commit | 0d6c26b9aa607ff14e14e6488bace207e324022a (patch) | |
| tree | 08c8900cc47d2b3aafa41dc37f96b36452584829 /docs/commentary | |
| parent | dcbb72306821e0856c32944a54ea93902ef2949f (diff) | |
Highlight [] as list brackets, like ⟨⟩
Diffstat (limited to 'docs/commentary')
| -rw-r--r-- | docs/commentary/history.html | 4 | ||||
| -rw-r--r-- | docs/commentary/problems.html | 4 | ||||
| -rw-r--r-- | docs/commentary/why.html | 10 |
3 files changed, 9 insertions, 9 deletions
diff --git a/docs/commentary/history.html b/docs/commentary/history.html index d1063fdd..f6955a71 100644 --- a/docs/commentary/history.html +++ b/docs/commentary/history.html @@ -208,12 +208,12 @@ <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"><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>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='Bracket'>[]</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"><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 consensus 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"><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='Head'>::</span></code>, but J only has the function <code><span class='Value'>[</span><span class='Head'>:</span></code> to unconditionally throw an error, with no way to set a message.</p> +<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='Head'>::</span></code>, but J only has the function <code><span class='Bracket'>[</span><span class='Head'>:</span></code> to unconditionally throw an error, with no way to set a message.</p> <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. Although I considered swapping subjects and functions, I ended up using exactly the conventions of his APL <a href="https://abrudz.github.io/style/#nc">style guide</a>.</p> <h4 id="headers"><a class="header" href="#headers">Headers</a></h4> diff --git a/docs/commentary/problems.html b/docs/commentary/problems.html index 38d41ea9..2937be17 100644 --- a/docs/commentary/problems.html +++ b/docs/commentary/problems.html @@ -35,7 +35,7 @@ <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 in BQN is to just say give your functions names and don't do this. But <a href="ltr.html">left to right</a> programming beckons.</p> <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 syntax <code><span class='Nothing'>·</span></code>, which acts like J's Cap (<code><span class='Value'>[</span><span class='Head'>:</span></code>) in a train, but still a minor frustration.</p> +<p>If you have the normal mix of monads and dyads you'll need a lot of parentheses and might end up abusing <code><span class='Modifier2'>⟜</span></code>. Largely solved with the Nothing syntax <code><span class='Nothing'>·</span></code>, which acts like J's Cap (<code><span class='Bracket'>[</span><span class='Head'>:</span></code>) in a train, but still a minor frustration.</p> <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>. Another form of Under that's sometimes wanted is <code><span class='Brace'>{</span><span class='Value'>𝕨</span><span class='Modifier2'>⊸</span><span class='Function'>𝔽</span><span class='Modifier2'>⌾</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>. One modifier can only do so much.</p> <h3 id="list-splicing-is-fiddly"><a class="header" href="#list-splicing-is-fiddly">List splicing is fiddly</a></h3> @@ -102,7 +102,7 @@ <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="high-rank-array-notation-awkwardness"><a class="header" href="#high-rank-array-notation-awkwardness">High-rank array notation awkwardness</a></h3> -<p>The notation <code><span class='Value'>[]</span></code> will be added for high-rank arrays, the same as BQN's lists <code><span class='Bracket'>⟨⟩</span></code> except it mixes at the end. It 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? A more concrete point of awkwardness is that literal notations can only form arrays with rank 1 or more, preventing unit arrays from being destructured. Syntax with <code><span class='Function'><</span></code> and <code><span class='Value'>[]</span></code> would be complete over non-empty arrays.</p> +<p>The notation <code><span class='Bracket'>[]</span></code> will be added for high-rank arrays, the same as BQN's lists <code><span class='Bracket'>⟨⟩</span></code> except it mixes at the end. It 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? A more concrete point of awkwardness is that literal notations can only form arrays with rank 1 or more, preventing unit arrays from being destructured. Syntax with <code><span class='Function'><</span></code> and <code><span class='Bracket'>[]</span></code> would be complete over non-empty arrays.</p> <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 on that. Kind of awkward, but better than it used to be before one-argument Assert was changed to use <code><span class='Value'>𝕩</span></code> for the message. The issue generally applies to high-quality tools built in BQN, where giving the user good errors is a priority.</p> <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> diff --git a/docs/commentary/why.html b/docs/commentary/why.html index 158dc679..9ab7e0a0 100644 --- a/docs/commentary/why.html +++ b/docs/commentary/why.html @@ -14,7 +14,7 @@ <p>BQN is more like APL, but adopts some of the developments made by J as well. However, it's much simpler than both, with fewer and less overloaded primitives as well as less special syntax (J has fewer syntactic rules, but more special cases handled during execution that I think <em>should</em> have been implemented with syntax).</p> <p>The major differences are listed on <a href="../index.html#whats-the-language-like">the front page</a> ("But it's redesigned…"): <a href="../doc/based.html">based arrays</a>, <a href="../doc/arrayrepr.html">list notation</a>, <a href="../doc/context.html">context-free grammar</a> and <a href="../doc/functional.html">first-class functions</a>, <a href="../doc/primitive.html">reworked primitives</a>, and dedicated <a href="../doc/namespace.html">namespace syntax</a>.</p> <p>In addition to these, BQN's <a href="../doc/block.html">block system</a> extends APL dfns with headers, adding some very useful functionality: the header specifies block type and argument names, and also allows for simple pattern matching when used with multiple block bodies.</p> -<p>Since this section gets into the details, it's worth highlighting stranding, a feature I think of as an obvious improvement but that many BQN newcomers see as an obvious sign that I don't know what I'm doing! My full argument for this decision is <a href="../doc/arrayrepr.html#why-not-whitespace">here</a>; the two key points are that stranding is a source of ambiguity that can strike at any time, requiring a correction with <code><span class='Function'>⊢</span></code> or <code><span class='Value'>]</span></code>, and that typing <code><span class='Ligature'>‿</span></code> is really not hard I promise.</p> +<p>Since this section gets into the details, it's worth highlighting stranding, a feature I think of as an obvious improvement but that many BQN newcomers see as an obvious sign that I don't know what I'm doing! My full argument for this decision is <a href="../doc/arrayrepr.html#why-not-whitespace">here</a>; the two key points are that stranding is a source of ambiguity that can strike at any time, requiring a correction with <code><span class='Function'>⊢</span></code> or <code><span class='Bracket'>]</span></code>, and that typing <code><span class='Ligature'>‿</span></code> is really not hard I promise.</p> <p>BQN's heavier-weight <code><span class='Bracket'>⟨⟩</span></code> syntax for lists also has its own advantages, because it can be formatted nicely across multiple lines, and also allows functions and modifiers to be used easily as elements. Being able to easily map over a list of functions is surprisingly useful!</p> <p>BQN has no built-in control structures, which can be quite an adjustment coming from certain styles of APL or J. The <a href="../doc/control.html">control structures</a> page gives some ways to write in a more imperative style, but it's definitely not the same.</p> <p>Primitives in BQN are pure functions that don't depend on interpreter settings. The following kinds of interpreter state don't apply:</p> @@ -27,10 +27,10 @@ <h3 id="apl"><a class="header" href="#apl">APL</a></h3> <p><em>See also the <a href="../doc/fromDyalog.html">BQN-Dyalog APL dictionary</a>. I compare to Dyalog here as it's the most widely used dialect.</em></p> <p>BQN cleans up some awkward syntax left over from when each APL operator was special: the outer product is written <code><span class='Function'>Fn</span><span class='Modifier'>⌜</span></code> rather than <code><span class='Modifier2'>∘</span><span class='Value'>.fn</span></code>, and reduction <code><span class='Function'>Fn</span><span class='Modifier'>´</span> <span class='Value'>arr</span></code> is separated from compress <code><span class='Value'>b</span><span class='Function'>/</span><span class='Value'>arr</span></code> instead of <a href="https://aplwiki.com/wiki/Function-operator_overloading">overloading</a>.</p> -<p>BQN adopts <a href="../doc/leading.html">leading axis theory</a> as developed in SHARP APL and applied in A+ and J. With this it can collapse APL pairs such as <code><span class='Function'>⌽</span><span class='Value'>⊖</span></code> and <code><span class='Function'>/</span><span class='Value'>⌿</span></code> to one primitive each, and remove APL's complicated function axis (such as <code><span class='Function'>⌽</span><span class='Value'>[</span><span class='Number'>2</span><span class='Value'>]</span></code>) mechanism. The Rank modifier <code><span class='Modifier2'>⎉</span></code> then applies these primitives to non-leading axes. While this method is required in J and also favored by many users of Dyalog APL, it definitely doesn't enjoy universal support—it can be harder to learn, and less convenient for some common cases. Summing rows with <code><span class='Function'>+/</span></code> in APL is quite convenient, and BQN's <code><span class='Function'>+</span><span class='Modifier'>˝</span><span class='Modifier2'>⎉</span><span class='Number'>1</span></code>, or <code><span class='Function'>+</span><span class='Modifier'>˝˘</span></code> for matrices, just aren't as nice.</p> +<p>BQN adopts <a href="../doc/leading.html">leading axis theory</a> as developed in SHARP APL and applied in A+ and J. With this it can collapse APL pairs such as <code><span class='Function'>⌽</span><span class='Value'>⊖</span></code> and <code><span class='Function'>/</span><span class='Value'>⌿</span></code> to one primitive each, and remove APL's complicated function axis (such as <code><span class='Function'>⌽</span><span class='Bracket'>[</span><span class='Number'>2</span><span class='Bracket'>]</span></code>) mechanism. The Rank modifier <code><span class='Modifier2'>⎉</span></code> then applies these primitives to non-leading axes. While this method is required in J and also favored by many users of Dyalog APL, it definitely doesn't enjoy universal support—it can be harder to learn, and less convenient for some common cases. Summing rows with <code><span class='Function'>+/</span></code> in APL is quite convenient, and BQN's <code><span class='Function'>+</span><span class='Modifier'>˝</span><span class='Modifier2'>⎉</span><span class='Number'>1</span></code>, or <code><span class='Function'>+</span><span class='Modifier'>˝˘</span></code> for matrices, just aren't as nice.</p> <p>Arguably BQN cuts down the set of primitives too much. Base conversion <code><span class='Value'>⊥⊤</span></code>, partitioning <code><span class='Value'>⊂⊆</span></code>, and matrix division <code><span class='Value'>⌹</span></code> are commonly asked-for primitives, but they don't match <a href="primitive.html">my conception</a> of a primitive. And while each can be implemented (with short snippets, other than <code><span class='Value'>⌹</span></code> which requires a library), there's definitely a convenience loss. But there's always <a href="../doc/rebqn.html">ReBQN</a>…</p> <p>BQN's Power modifier <code><span class='Modifier2'>⍟</span></code> allows an array operand to specify multiple results, for example <code><span class='Function'>Fn</span><span class='Modifier2'>⍟</span><span class='Paren'>(</span><span class='Function'>↕</span><span class='Number'>4</span><span class='Paren'>)</span></code> to get 0 up to 3 iterations. Intermediate results are saved, so the number of calls only depends on the highest iteration number present. On the other hand, BQN has no direct equivalent of Power Limit <code><span class='Value'>⍣</span><span class='Function'>≡</span></code>, requiring it to be <a href="https://mlochbaum.github.io/bqncrate/?q=power%20limit">implemented manually</a>.</p> -<p>An APL selective assignment <code><span class='Value'>arr[</span><span class='Number'>2</span> <span class='Number'>3</span><span class='Value'>]</span><span class='Function'>+</span><span class='Gets'>←</span><span class='Number'>1</span></code> should usually be written with Under in BQN: <code><span class='Number'>1</span><span class='Modifier2'>⊸</span><span class='Function'>+</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Modifier2'>⊸</span><span class='Function'>⊏</span><span class='Paren'>)</span><span class='Value'>arr</span></code> (but the correspondence might not always be so direct). You can think of this as a very fancy At (<code><span class='String'>@</span></code>) operator, that lets you pull out an arbitrary part of an array.</p> +<p>An APL selective assignment <code><span class='Value'>arr</span><span class='Bracket'>[</span><span class='Number'>2</span> <span class='Number'>3</span><span class='Bracket'>]</span><span class='Function'>+</span><span class='Gets'>←</span><span class='Number'>1</span></code> should usually be written with Under in BQN: <code><span class='Number'>1</span><span class='Modifier2'>⊸</span><span class='Function'>+</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Modifier2'>⊸</span><span class='Function'>⊏</span><span class='Paren'>)</span><span class='Value'>arr</span></code> (but the correspondence might not always be so direct). You can think of this as a very fancy At (<code><span class='String'>@</span></code>) operator, that lets you pull out an arbitrary part of an array.</p> <p>Dfns are adjusted in a few ways that make them more useful for general-purpose programming. A BQN block always runs to the last statement, so a block like <code><span class='Brace'>{</span><span class='Function'>Update</span> <span class='Value'>𝕩</span> <span class='Separator'>⋄</span> <span class='Number'>1</span><span class='Function'>+</span><span class='Value'>x</span><span class='Brace'>}</span></code> won't return early. Writing modification with <code><span class='Gets'>↩</span></code> makes it clearer which variable's which. Dfns also do a weird shadowing thing where <code><span class='Value'>a</span><span class='Gets'>←</span><span class='Number'>1</span><span class='Separator'>⋄</span><span class='Value'>a</span><span class='Gets'>←</span><span class='Number'>2</span></code> makes two different variables; in BQN this is an error because the second should use <code><span class='Gets'>↩</span></code>. Tradfns are removed entirely, along with control structures.</p> <p>BQN doesn't have an exact replacement for dfn guards, although the predicate <code><span class='Head'>?</span></code> can look similar: <code><span class='Brace'>{</span><span class='Number'>2</span><span class='Function'>|</span><span class='Value'>⍵</span> <span class='Head'>:</span> <span class='Number'>1</span><span class='Function'>+</span><span class='Number'>3</span><span class='Function'>×</span><span class='Value'>⍵</span> <span class='Separator'>⋄</span> <span class='Value'>⍵</span><span class='Function'>÷</span><span class='Number'>2</span><span class='Brace'>}</span></code> is equivalent to <code><span class='Brace'>{</span><span class='Number'>2</span><span class='Function'>|</span><span class='Value'>𝕩</span> <span class='Head'>?</span> <span class='Number'>1</span><span class='Function'>+</span><span class='Number'>3</span><span class='Function'>×</span><span class='Value'>𝕩</span> <span class='Head'>;</span> <span class='Value'>𝕩</span><span class='Function'>÷</span><span class='Number'>2</span><span class='Brace'>}</span></code>. But note that where APL uses the statement separator <code><span class='Separator'>⋄</span></code>, BQN uses the body separator <code><span class='Head'>;</span></code>. This means that the if-true branch in BQN can consist of multiple statements (including additional predicates), but also that the if-false branch can't access variables defined in or before the condition. In both cases the "better" behavior can be obtained with an extra set of braces and possibly assigning names to arguments <code><span class='Value'>⍵</span></code>/<code><span class='Value'>𝕩</span></code>. I think guards end up being cleaner when they work, and predicates are more versatile.</p> <p>BQN's namespaces have a dedicated syntax, are <em>much</em> easier to create than Dyalog namespaces, and have better performance. I use them all the time, and they feel like a natural part of the language.</p> @@ -46,9 +46,9 @@ <p>But J has its type advantages as well. I miss complex number support in BQN, as it's an optional extension that we haven't yet implemented. And BQN has a hard rule that only one numeric type is exposed to the programmer, which means high-precision integers and rationals aren't allowed at all for a float-based implementation. I think this rule is worth it because J's implicit type conversion is hard to predict and an unexpected numeric type can cause sporadic or subtle program errors.</p> <p>BQN uses a modifier <code><span class='Modifier2'>⟜</span></code> for J's hook, adding <code><span class='Modifier2'>⊸</span></code> for a reversed version (which I use nearly twice as often). This frees up the 2-train, which is made equivalent to Atop (<code><span class='Modifier2'>∘</span></code>). It's the system Roger Hui came to advocate, since he argued in favor of a hook conjunction <a href="https://code.jsoftware.com/wiki/Essays/Hook_Conjunction%3F">here</a> and made 2-train an Atop when he brought it to Dyalog APL. As an example, the J hook <code><span class='Paren'>(</span><span class='Comment'>#~0&<:)</span></code> to remove negative numbers becomes <code><span class='Number'>0</span><span class='Modifier2'>⊸</span><span class='Function'>≤</span><span class='Modifier2'>⊸</span><span class='Function'>/</span></code> in BQN. Hooks are also the topic of <a href="https://www.arraycast.com/episodes/episode17-tacit4-the-dyadic-hook">Array Cast episode 14</a>, where the panel points out that in J, adding a verb at the far left of a dyadic train changes the rest of the train from dyadic to monadic or vice-versa, an effect that doesn't happen in BQN.</p> <p>J locales are not first-class values, and BQN namespaces are. I think BQN's namespaces are a lot more convenient to construct, although it is lacking an inheritance mechanism (but J's path system can become confusing quickly). More importantly, BQN namespaces (and closures) are garbage collected. J locales leak unless manually freed by the programmer. More generally, J has no mutable data at all, and to simulate it properly you'd have to write your own tracing garbage collection as the J interpreter doesn't have any. I discussed this issue some in <a href="http://www.jsoftware.com/pipermail/programming/2021-April/058006.html">this J forum thread</a>.</p> -<p>In J, each function has a built-in rank attribute: for example the ranks of <code><span class='Function'>+</span></code> are <code><span class='Number'>0</span> <span class='Number'>0</span> <span class='Number'>0</span></code>. This rank is accessed by the "close" compositions <code><span class='String'>@</span></code>, <code><span class='Value'>&</span></code>, and <code><span class='Value'>&.</span></code>. Choosing the shorter form for the close compositions—for example <code><span class='String'>@</span></code> rather than <code><span class='String'>@</span><span class='Head'>:</span></code>—is often considered a mistake within the J community. And function ranks are unreliable: consider that the ranks of <code><span class='Value'>]</span><span class='String'>@</span><span class='Head'>:</span><span class='Function'>+</span></code>, a function that always has the same result as <code><span class='Function'>+</span></code>, are <code><span class='Modifier2'>_</span> <span class='Modifier2'>_</span> <span class='Modifier2'>_</span></code>. In BQN there aren't any close compositions at all, and no function ranks. J's <code><span class='Value'>&.</span><span class='Function'>></span></code> is simply <code><span class='Modifier'>¨</span></code>, and other close compositions, in my opinion, just aren't needed.</p> +<p>In J, each function has a built-in rank attribute: for example the ranks of <code><span class='Function'>+</span></code> are <code><span class='Number'>0</span> <span class='Number'>0</span> <span class='Number'>0</span></code>. This rank is accessed by the "close" compositions <code><span class='String'>@</span></code>, <code><span class='Value'>&</span></code>, and <code><span class='Value'>&.</span></code>. Choosing the shorter form for the close compositions—for example <code><span class='String'>@</span></code> rather than <code><span class='String'>@</span><span class='Head'>:</span></code>—is often considered a mistake within the J community. And function ranks are unreliable: consider that the ranks of <code><span class='Bracket'>]</span><span class='String'>@</span><span class='Head'>:</span><span class='Function'>+</span></code>, a function that always has the same result as <code><span class='Function'>+</span></code>, are <code><span class='Modifier2'>_</span> <span class='Modifier2'>_</span> <span class='Modifier2'>_</span></code>. In BQN there aren't any close compositions at all, and no function ranks. J's <code><span class='Value'>&.</span><span class='Function'>></span></code> is simply <code><span class='Modifier'>¨</span></code>, and other close compositions, in my opinion, just aren't needed.</p> <p>J has several adverbs (key, prefix, infix, outfix…) to slice up an argument in various ways and apply a verb to those parts. In BQN, I rejected this approach: there are 1-modifiers for basic iteration patterns, and functions such as <a href="../doc/group.html">Group</a> (<code><span class='Function'>⊔</span></code>) that do the slicing but don't apply anything. So <code><span class='Function'></</span><span class='Value'>.~a</span></code> is <code><span class='Function'>⊐</span><span class='Modifier2'>⊸</span><span class='Function'>⊔</span><span class='Value'>a</span></code>, but <code><span class='Value'>fn</span><span class='Function'>/</span><span class='Value'>.~a</span></code> is <code><span class='Function'>>Fn</span><span class='Modifier'>¨</span><span class='Function'>⊐</span><span class='Modifier2'>⊸</span><span class='Function'>⊔</span><span class='Value'>a</span></code> (I also reject J's implicit merge except for the Rank modifier, as I don't think function results should be homogeneous by default). BQN's approach composes better, and is more predictable from a performance perspective.</p> -<p>Gerunds are J's answer to BQN's first-class functions. For example J's <code><span class='Paren'>(</span><span class='Value'>%&</span><span class='Number'>2</span><span class='Paren'>)</span><span class='Modifier'>`</span><span class='Paren'>(</span><span class='Number'>1</span><span class='Function'>+</span><span class='Number'>3</span><span class='Value'>*]</span><span class='Paren'>)</span><span class='String'>@</span><span class='Value'>.</span><span class='Paren'>(</span><span class='Number'>2</span><span class='Value'>&</span><span class='Function'>|</span><span class='Paren'>)</span></code> would be written <code><span class='Number'>2</span><span class='Modifier2'>⊸</span><span class='Function'>|</span><span class='Modifier2'>◶</span><span class='Bracket'>⟨</span><span class='Function'>÷</span><span class='Modifier2'>⟜</span><span class='Number'>2</span><span class='Separator'>,</span><span class='Number'>1</span><span class='Function'>+</span><span class='Number'>3</span><span class='Function'>×⊢</span><span class='Bracket'>⟩</span></code> with a list of functions. I think lists of functions are a big improvement, since there's no need to convert between gerund and function, and no worries about arrays that just happen to be valid gerunds (worried about losing the ability to construct gerunds? Constructing tacit functions in BQN is much easier). The usability gap widens because passing J functions around either as values or gerunds has presents some highly idiosyncratic challenges, discussed below.</p> +<p>Gerunds are J's answer to BQN's first-class functions. For example J's <code><span class='Paren'>(</span><span class='Value'>%&</span><span class='Number'>2</span><span class='Paren'>)</span><span class='Modifier'>`</span><span class='Paren'>(</span><span class='Number'>1</span><span class='Function'>+</span><span class='Number'>3</span><span class='Value'>*</span><span class='Bracket'>]</span><span class='Paren'>)</span><span class='String'>@</span><span class='Value'>.</span><span class='Paren'>(</span><span class='Number'>2</span><span class='Value'>&</span><span class='Function'>|</span><span class='Paren'>)</span></code> would be written <code><span class='Number'>2</span><span class='Modifier2'>⊸</span><span class='Function'>|</span><span class='Modifier2'>◶</span><span class='Bracket'>⟨</span><span class='Function'>÷</span><span class='Modifier2'>⟜</span><span class='Number'>2</span><span class='Separator'>,</span><span class='Number'>1</span><span class='Function'>+</span><span class='Number'>3</span><span class='Function'>×⊢</span><span class='Bracket'>⟩</span></code> with a list of functions. I think lists of functions are a big improvement, since there's no need to convert between gerund and function, and no worries about arrays that just happen to be valid gerunds (worried about losing the ability to construct gerunds? Constructing tacit functions in BQN is much easier). The usability gap widens because passing J functions around either as values or gerunds has presents some highly idiosyncratic challenges, discussed below.</p> <h4 id="named-functions"><a class="header" href="#named-functions">Named functions</a></h4> <p>Its impact on the programmer is smaller than a lot of the issues above, but this section describes a behavior that I find pretty hard to justify. What does the identifier <code><span class='Value'>fn</span></code> indicate in a J expression? The value of <code><span class='Value'>fn</span></code> in the current scope, one might suppose. Nope—only if the value is a noun. Let's make it a function.</p> <pre> <span class='Value'>fn</span> <span class='Function'>=</span><span class='Head'>:</span> <span class='Function'>-</span> |
