diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-12-02 14:45:59 -0500 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-12-02 15:06:12 -0500 |
| commit | 55c40e75dde0ddad39a305f29e036ec88c85babe (patch) | |
| tree | 3475a3c3e600227468828c507a241763e58f2085 /doc | |
| parent | 1b8aab1ebfc36888d58d5347f7723e4bd1c5031c (diff) | |
Move problems.md to commentary folder
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/based.md | 2 | ||||
| -rw-r--r-- | doc/context.md | 2 | ||||
| -rw-r--r-- | doc/functional.md | 2 | ||||
| -rw-r--r-- | doc/prefixes.md | 2 | ||||
| -rw-r--r-- | doc/train.md | 2 |
5 files changed, 5 insertions, 5 deletions
diff --git a/doc/based.md b/doc/based.md index b9c5d3e9..83fe74e8 100644 --- a/doc/based.md +++ b/doc/based.md @@ -46,7 +46,7 @@ Nested array theory can seem simpler to use, because the programmer never has to A property that might warn about dangerous issues like this is that nested array theory tends to create *inversions* 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. -In some cases nested array theory can remove a depth issue entirely, and not just partially. Most notable is the [search function result depth](../problems.md#search-function-depth) 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. +In some cases nested array theory can remove a depth issue entirely, and not just partially. Most notable is the [search function result depth](../commentary/problems.md#search-function-depth) 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. ## Versus the boxed array model diff --git a/doc/context.md b/doc/context.md index bf2183bb..516a5f18 100644 --- a/doc/context.md +++ b/doc/context.md @@ -19,7 +19,7 @@ Here, the lowercase spelling indicates that `a` and `e` are to be treated as sub ## Is grammatical context really a problem? -Yes, in the sense of [problems with BQN](../problems.md). 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. +Yes, in the sense of [problems with BQN](../commentary/problems.md). 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. 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 `⍳⍨=⍳∘≢` consists of six largely unfamiliar characters with little to distinguish them (in fact, the one obvious bit of structure, the repeated `⍳`, is misleading as it means different things in each case!). Simply placing parentheses into the expression, like `(⍳⍨)=(⍳∘≢)`, 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, `⊐˜=↕∘≠`, 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 `˜` are 1-modifiers and characters like `∘` with unbroken circles are 2-modifiers before beginning to learn the BQN grammar that will explain how to tie the various parts together. diff --git a/doc/functional.md b/doc/functional.md index fde4d3f7..1d55e8b8 100644 --- a/doc/functional.md +++ b/doc/functional.md @@ -88,7 +88,7 @@ Another topic we are interested in is *lexical scoping* and *closures*. Lexical 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 bug](http://www.jsoftware.com/pipermail/programming/2013-January/031260.html) 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! -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 `F G x` with functions `F` and `G` and an array `x` 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 `⍎'+'` returns the function `+`). Dyalog's `⎕OR` 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 `⎕OR`s even share a form of BQN's [syntactic type erasure](../problems.md#syntactic-type-erasure), as a `⎕OR` 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 `⎕OR`s, so they don't work very well as a first-class function mechanism. +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 `F G x` with functions `F` and `G` and an array `x` 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 `⍎'+'` returns the function `+`). Dyalog's `⎕OR` 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 `⎕OR`s even share a form of BQN's [syntactic type erasure](../commentary/problems.md#syntactic-type-erasure), as a `⎕OR` 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 `⎕OR`s, so they don't work very well as a first-class function mechanism. 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. diff --git a/doc/prefixes.md b/doc/prefixes.md index 54693a4f..41cbd447 100644 --- a/doc/prefixes.md +++ b/doc/prefixes.md @@ -69,7 +69,7 @@ This array can be [joined](join.md), indicating that the length of each inner ax ∾ 1‿1 ↓ ((↕1+≢)<⎉2∘↕¨<) 3‿2⥊"abcdef" -But Prefixes and Suffixes [don't have](../problems.md#cant-take-prefixes-or-suffixes-on-multiple-axes) 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 [definitions](#definition) above. +But Prefixes and Suffixes [don't have](../commentary/problems.md#cant-take-prefixes-or-suffixes-on-multiple-axes) 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 [definitions](#definition) above. Prefs ← (↕1+≢)↑¨< Suffs ← (↕1+≢)↓¨< diff --git a/doc/train.md b/doc/train.md index ece363a4..6bacc75a 100644 --- a/doc/train.md +++ b/doc/train.md @@ -92,7 +92,7 @@ We might make the first train above easier to read by using Atop (`∘`) instead These two forms have a different emphasis, because the first breaks into subfunctions `⍷∘∧` and `|` and the second into `⍷` and `∧|`. It's more common to use `⍷∘∧` as a unit than `∧|`, so in this case `⍷∘∧|` is probably the better train. -Many one-argument functions strung together is [a major weakness](../problems.md#trains-dont-like-monads) for train syntax. If there are many such functions it's probably best to stick with a block function instead! +Many one-argument functions strung together is [a major weakness](../commentary/problems.md#trains-dont-like-monads) for train syntax. If there are many such functions it's probably best to stick with a block function instead! {⍷∧|𝕩} 3‿4‿¯3‿¯2‿0 |
