diff options
Diffstat (limited to 'docs/doc')
| -rw-r--r-- | docs/doc/based.html | 2 | ||||
| -rw-r--r-- | docs/doc/context.html | 2 | ||||
| -rw-r--r-- | docs/doc/functional.html | 2 | ||||
| -rw-r--r-- | docs/doc/prefixes.html | 2 | ||||
| -rw-r--r-- | docs/doc/train.html | 2 |
5 files changed, 5 insertions, 5 deletions
diff --git a/docs/doc/based.html b/docs/doc/based.html index e070bb94..ced213c8 100644 --- a/docs/doc/based.html +++ b/docs/doc/based.html @@ -44,7 +44,7 @@ <p>The <a href="https://aplwiki.com/wiki/Array_model#Nested_array_theory">nested array model</a> of NARS, APL2, Dyalog, and GNU APL can be constructed from the based model by adding a rule: a unit (or "scalar" in APL) array containing an atom is equivalent to that atom. The equivalents of atoms in nested array theory are thus called "simple scalars", and they are considered arrays but share the characteristics of BQN atoms. Nested arrays don't form an inductive type, because simple scalars contain themselves.</p> <p>Nested array theory can seem simpler to use, because the programmer never has to worry about simple scalars being enclosed the wrong number of times: all these encloses have been identified with each other. For example, <code><span class='String'>'</span><span class='Value'>abcd</span><span class='String'>'</span><span class='Value'>[</span><span class='Number'>2</span><span class='Value'>]</span></code> returns a character while BQN's <code><span class='Number'>2</span><span class='Function'>⊏</span><span class='String'>"abcd"</span></code> returns an array containing a character. However, these issues usually still appear with more complex arrays: <code><span class='String'>'</span><span class='Value'>ab</span><span class='String'>'</span> <span class='Number'>1</span> <span class='String'>'</span><span class='Value'>ef</span><span class='String'>'</span><span class='Value'>[</span><span class='Number'>2</span><span class='Value'>]</span></code> (here spaces are used for stranding) is not a string but an enclosed string!</p> <p>A property that might warn about dangerous issues like this is that nested array theory tends to create <em>inversions</em> where the depth of a particular array depends on its rank (reversing the normal hierarchy of depth→rank→shape). A 1-character string has depth 1, but when its rank is reduced to 0, its depth is reduced as well.</p> -<p>In some cases nested array theory can remove a depth issue entirely, and not just partially. Most notable is the <a href="../problems.html#search-function-depth">search function result depth</a> issue, in which it's impossible for a search function in BQN to return an atomic number because it always returns an array. Nested array theory doesn't have this issue since a scalar number is "just a number", and more complicated arrays can't cause problems because a search function's result is always a numeric array. The other half of the problem, about the non-principal argument depth, is only partly hidden, and causes problems for example when searching for a single string out of a list of strings.</p> +<p>In some cases nested array theory can remove a depth issue entirely, and not just partially. Most notable is the <a href="../commentary/problems.html#search-function-depth">search function result depth</a> issue, in which it's impossible for a search function in BQN to return an atomic number because it always returns an array. Nested array theory doesn't have this issue since a scalar number is "just a number", and more complicated arrays can't cause problems because a search function's result is always a numeric array. The other half of the problem, about the non-principal argument depth, is only partly hidden, and causes problems for example when searching for a single string out of a list of strings.</p> <h2 id="versus-the-boxed-array-model">Versus the boxed array model</h2> <p>The <a href="https://aplwiki.com/wiki/Array_model#Boxes">boxed array model</a> of SHARP APL, A+, and J is an inductive system like BQN's. But this model uses arrays as the base case: numeric and character arrays are the simplest kind of data allowed, and "a number" means a rank-0 numeric array. The inductive step is the array of boxes; as with numbers "a box" is simply a rank-0 array of boxes.</p> <p>Numeric and character arrays in this system have depth 0. In general these correspond to arrays of depth 1 in BQN, but because there's no lower depth they are also used where BQN atoms would appear. For example, both Shape (<code><span class='Value'>$</span></code>) and Length (<code><span class='Comment'>#</span></code>) return depth-0 results in J. For an array <code><span class='Value'>a</span></code> with rank at least 1, the length <code><span class='Comment'>#a</span></code> is exactly <code><span class='Value'>[</span><span class='Function'>/</span> <span class='Value'>$</span> <span class='Value'>a</span></code>, while the identical BQN code <code><span class='Function'>⊣</span><span class='Modifier'>˝</span> <span class='Function'>≢</span> <span class='Value'>a</span></code> returns not <code><span class='Function'>≠</span> <span class='Value'>a</span></code> but <code><span class='Function'><</span> <span class='Function'>≠</span> <span class='Value'>a</span></code>. Like the nested model, the boxed model can hide depth issues that occur at lower depths but generally reveals them at higher depths.</p> diff --git a/docs/doc/context.html b/docs/doc/context.html index 1b5e949c..8c0ea92e 100644 --- a/docs/doc/context.html +++ b/docs/doc/context.html @@ -17,7 +17,7 @@ </pre> <p>Here, the lowercase spelling indicates that <code><span class='Value'>a</span></code> and <code><span class='Value'>e</span></code> are to be treated as subjects ("arrays" in APL) while the uppercase spelling of variables <code><span class='Function'>B</span></code> and <code><span class='Function'>C</span></code> are used as functions and <code><span class='Modifier'>_d</span></code> is a 1-modifier ("monadic operator"). Like parentheses for function application, the spelling is not inherent to the variable values used, but instead indicates their grammatical role in this particular expression. A variable has no inherent spelling and can be used in any role, so the names <code><span class='Value'>a</span></code>, <code><span class='Function'>A</span></code>, <code><span class='Modifier'>_a</span></code>, and <code><span class='Modifier2'>_a_</span></code> all refer to exact same variable, but in different roles; typically we use the lowercase name to refer to the variable in isolation—all values are nouns when speaking about them in English. While we still don't know anything about what values <code><span class='Value'>a</span></code>, <code><span class='Value'>b</span></code>, <code><span class='Value'>c</span></code>, and so on have, we know how they interact in the line of code above.</p> <h2 id="is-grammatical-context-really-a-problem">Is grammatical context really a problem?</h2> -<p>Yes, in the sense of <a href="../problems.html">problems with BQN</a>. A grammar that uses context is harder for humans to read and machines to execute. A particular difficulty is that parts of an expression you don't yet understand can interfere with parts you do, making it difficult to work through an unknown codebase.</p> +<p>Yes, in the sense of <a href="../commentary/problems.html">problems with BQN</a>. A grammar that uses context is harder for humans to read and machines to execute. A particular difficulty is that parts of an expression you don't yet understand can interfere with parts you do, making it difficult to work through an unknown codebase.</p> <p>One difficulty beginners to APL will encounter is that code in APL at first appears like a string of undifferentiated symbols. For example, a tacit Unique Mask implementation <code><span class='Value'>⍳⍨</span><span class='Function'>=</span><span class='Value'>⍳</span><span class='Modifier2'>∘</span><span class='Function'>≢</span></code> consists of six largely unfamiliar characters with little to distinguish them (in fact, the one obvious bit of structure, the repeated <code><span class='Value'>⍳</span></code>, is misleading as it means different things in each case!). Simply placing parentheses into the expression, like <code><span class='Paren'>(</span><span class='Value'>⍳⍨</span><span class='Paren'>)</span><span class='Function'>=</span><span class='Paren'>(</span><span class='Value'>⍳</span><span class='Modifier2'>∘</span><span class='Function'>≢</span><span class='Paren'>)</span></code>, can be a great help to a beginner, and part of learning APL is to naturally see where the parentheses should go. The equivalent BQN expression, <code><span class='Function'>⊐</span><span class='Modifier'>˜</span><span class='Function'>=↕</span><span class='Modifier2'>∘</span><span class='Function'>≠</span></code>, will likely appear equally intimidating at first, but the path to learning which things apply to which is much shorter: rather than learning the entire list of APL primitives, a beginner just needs to know that superscript characters like <code><span class='Modifier'>˜</span></code> are 1-modifiers and characters like <code><span class='Modifier2'>∘</span></code> with unbroken circles are 2-modifiers before beginning to learn the BQN grammar that will explain how to tie the various parts together.</p> <p>This sounds like a distant concern to a master of APL or a computer that has no difficulty memorizing a few dozen glyphs. Quite the opposite: the same concern applies to variables whenever you begin work with an unfamiliar codebase! Many APL programmers even enforce variable name conventions to ensure they know the class of a variable. By having such a system built in, BQN keeps you from having to rely on programmers following a style guide, and also allows greater flexibility, including <a href="functional.html">functional programming</a>, as we'll see later.</p> <p>Shouldn't a codebase define all the variables it uses, so we can see their class from the definition? Not always: consider that in a language with libraries, code might be imported from dependencies. Many APLs also have some dynamic features that can allow a variable to have more than one class, such as the <code><span class='Value'>⍺</span><span class='Gets'>←</span><span class='Function'>⊢</span></code> pattern in a dfn that makes <code><span class='Value'>⍺</span></code> an array in the dyadic case but a function in the monadic case. Regardless, searching for a definition somewhere in the code is certainly a lot more work than knowing the class just from looking! One final difficulty is that even one unknown can delay understanding of an entire expression. Suppose in <code><span class='Function'>A</span> <span class='Function'>B</span> <span class='Value'>c</span></code>, <code><span class='Function'>B</span></code> is a function and <code><span class='Value'>c</span></code> is an array, and both values are known to be constant. If <code><span class='Function'>A</span></code> is known to be a function (even if its value is not yet known), its right argument <code><span class='Function'>B</span> <span class='Value'>c</span></code> can be evaluated ahead of time. But if <code><span class='Function'>A</span></code>'s type isn't known, it's impossible to know if this optimization is worth it, because if it is an array, <code><span class='Function'>B</span></code> will instead be called dyadically.</p> diff --git a/docs/doc/functional.html b/docs/doc/functional.html index 4a5b7495..7e3b3900 100644 --- a/docs/doc/functional.html +++ b/docs/doc/functional.html @@ -63,7 +63,7 @@ <p>Another topic we are interested in is <em>lexical scoping</em> and <em>closures</em>. Lexical scoping means that the realm in which a variable exists is determined by its containing context (in BQN, the surrounding set of curly braces <code><span class='Brace'>{}</span></code>, if any) within the source code. A closure is really an implementation mechanism, but it's often used to refer to a property of lexical scoping that appears when functions defined in a particular block can be accessed after the block finishes execution. For example, they might be returned from a function or assigned to a variable outside of that function's scope. In this case the functions can still access variables in the original scope. I consider this property to be a requirement for a correct lexical scoping implementation, but it's traditionally not a part of APL: implementation might not have lexical scoping (for example, J and I believe A+ use static scoping where functions can't access variables in containing scopes) or might cut off the scope once execution ends, leading to value errors that one wouldn't predict from the rules of lexical scoping.</p> <h2 id="functions-in-apl">Functions in APL</h2> <p>This seems like a good place for a brief and entirely optional discussion of how APL handles functions and why it does it this way. As mentioned above, APL's functions are second class rather than first class. However, it's worth noting that the barriers to making functions first-class objects have been entirely syntactic and conceptual, not technical. In fact, the J language has for a long time had <a href="http://www.jsoftware.com/pipermail/programming/2013-January/031260.html">a bug</a> that allows an array containing a function to be created: by selecting from the array, the function itself can even be passed through tacit functions as an argument!</p> -<p>The primary reason why APL doesn't allow functions to be passed as arguments is probably syntax: in particular, there's no way to say that a function should be used as the left argument to another function, as an expression like <code><span class='Function'>F</span> <span class='Function'>G</span> <span class='Value'>x</span></code> with functions <code><span class='Function'>F</span></code> and <code><span class='Function'>G</span></code> and an array <code><span class='Value'>x</span></code> will simply be evaluated as two monadic function applications. However, there's no syntactic rule that prevents a function from returning a function, and Dyalog APL for example allows this (so <code><span class='Value'>⍎</span><span class='String'>'+'</span></code> returns the function <code><span class='Function'>+</span></code>). Dyalog's <code><span class='Value'>⎕</span><span class='Function'>OR</span></code> is another interesting phenomenon in this context: it creates an array from a function or operator, which can then be used as an element or argument like any array. The mechanism is essentially the same as BQN's first class functions, and in fact <code><span class='Value'>⎕</span><span class='Function'>OR</span></code>s even share a form of BQN's <a href="../problems.html#syntactic-type-erasure">syntactic type erasure</a>, as a <code><span class='Value'>⎕</span><span class='Function'>OR</span></code> of a function passed as an operand magically becomes a function again. But outside of this property, it's cumbersome and slow to convert functions to and from <code><span class='Value'>⎕</span><span class='Function'>OR</span></code>s, so they don't work very well as a first-class function mechanism.</p> +<p>The primary reason why APL doesn't allow functions to be passed as arguments is probably syntax: in particular, there's no way to say that a function should be used as the left argument to another function, as an expression like <code><span class='Function'>F</span> <span class='Function'>G</span> <span class='Value'>x</span></code> with functions <code><span class='Function'>F</span></code> and <code><span class='Function'>G</span></code> and an array <code><span class='Value'>x</span></code> will simply be evaluated as two monadic function applications. However, there's no syntactic rule that prevents a function from returning a function, and Dyalog APL for example allows this (so <code><span class='Value'>⍎</span><span class='String'>'+'</span></code> returns the function <code><span class='Function'>+</span></code>). Dyalog's <code><span class='Value'>⎕</span><span class='Function'>OR</span></code> is another interesting phenomenon in this context: it creates an array from a function or operator, which can then be used as an element or argument like any array. The mechanism is essentially the same as BQN's first class functions, and in fact <code><span class='Value'>⎕</span><span class='Function'>OR</span></code>s even share a form of BQN's <a href="../commentary/problems.html#syntactic-type-erasure">syntactic type erasure</a>, as a <code><span class='Value'>⎕</span><span class='Function'>OR</span></code> of a function passed as an operand magically becomes a function again. But outside of this property, it's cumbersome and slow to convert functions to and from <code><span class='Value'>⎕</span><span class='Function'>OR</span></code>s, so they don't work very well as a first-class function mechanism.</p> <p>Another reason for APL's reluctance to adopt first-class functions is that Iverson and others seemed to believe that functions fundamentally are not a kind of data, because it's impossible to uniquely represent, compare, and order them. One effect of this viewpoint is J's gerund mechanism, which converts a function to an array representation, primarily so that lists of gerunds can be created. Gerunds are nested arrays containing character vectors at the leaves, so they are arrays as Iverson thought of them. However, I consider this conversion of functions to arrays, intended to avoid arrays that contain "black box" functions, to be a mistake: while it doesn't compromise the purity of arrays, it gives the illusion that a function corresponds to a particular array, which is not true from the mathematical perspective of functions as mappings from an arbitrary input to an output. I also think the experience of countless languages with first-class functions shows that there is no practical issue with arrays that contain functions. While having all arrays be concrete entities with a unique canonical representation seems desirable, I don't find the existence of arrays without this property to be detract from working with arrays that do have it.</p> <h2 id="functional-programming-in-bqn">Functional programming in BQN</h2> <p><em>Reminder: I am discussing only first-class functional programming here, and not other concepts like pure or typed functional programming!</em></p> diff --git a/docs/doc/prefixes.html b/docs/doc/prefixes.html index 37bda297..9ef7cbdd 100644 --- a/docs/doc/prefixes.html +++ b/docs/doc/prefixes.html @@ -167,7 +167,7 @@ ┘ ┘ ┘ ┘ </pre> -<p>But Prefixes and Suffixes <a href="../problems.html#cant-take-prefixes-or-suffixes-on-multiple-axes">don't have</a> any way to specify that they should work on multiple axes, and always work on exactly one. So to extend this pattern we will have to define multi-dimensional versions. This turns out to be very easy: just replace Length with Shape in the <a href="#definition">definitions</a> above.</p> +<p>But Prefixes and Suffixes <a href="../commentary/problems.html#cant-take-prefixes-or-suffixes-on-multiple-axes">don't have</a> any way to specify that they should work on multiple axes, and always work on exactly one. So to extend this pattern we will have to define multi-dimensional versions. This turns out to be very easy: just replace Length with Shape in the <a href="#definition">definitions</a> above.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=UHJlZnMg4oaQICjihpUxK+KJoinihpHCqDwKU3VmZnMg4oaQICjihpUxK+KJoinihpPCqDwKUHJlZnPCqFN1ZmZzIDPigL8y4qWKImFiY2RlZiI=">↗️</a><pre> <span class='Function'>Prefs</span> <span class='Gets'>←</span> <span class='Paren'>(</span><span class='Function'>↕</span><span class='Number'>1</span><span class='Function'>+≢</span><span class='Paren'>)</span><span class='Function'>↑</span><span class='Modifier'>¨</span><span class='Function'><</span> <span class='Function'>Suffs</span> <span class='Gets'>←</span> <span class='Paren'>(</span><span class='Function'>↕</span><span class='Number'>1</span><span class='Function'>+≢</span><span class='Paren'>)</span><span class='Function'>↓</span><span class='Modifier'>¨</span><span class='Function'><</span> <span class='Function'>Prefs</span><span class='Modifier'>¨</span><span class='Function'>Suffs</span> <span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Function'>⥊</span><span class='String'>"abcdef"</span> diff --git a/docs/doc/train.html b/docs/doc/train.html index d4eff715..4ae23b13 100644 --- a/docs/doc/train.html +++ b/docs/doc/train.html @@ -89,7 +89,7 @@ ⟨ 0 2 3 4 ⟩ </pre> <p>These two forms have a different emphasis, because the first breaks into subfunctions <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧</span></code> and <code><span class='Function'>|</span></code> and the second into <code><span class='Function'>⍷</span></code> and <code><span class='Function'>∧|</span></code>. It's more common to use <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧</span></code> as a unit than <code><span class='Function'>∧|</span></code>, so in this case <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧|</span></code> is probably the better train.</p> -<p>Many one-argument functions strung together is <a href="../problems.html#trains-dont-like-monads">a major weakness</a> for train syntax. If there are many such functions it's probably best to stick with a block function instead!</p> +<p>Many one-argument functions strung together is <a href="../commentary/problems.html#trains-dont-like-monads">a major weakness</a> for train syntax. If there are many such functions it's probably best to stick with a block function instead!</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=e+KNt+KIp3zwnZWpfSAz4oC/NOKAv8KvM+KAv8KvMuKAvzA=">↗️</a><pre> <span class='Brace'>{</span><span class='Function'>⍷∧|</span><span class='Value'>𝕩</span><span class='Brace'>}</span> <span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>¯3</span><span class='Ligature'>‿</span><span class='Number'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ </pre> |
