diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-26 21:00:25 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-26 21:00:25 -0400 |
| commit | b6185d5029e2adcc721c0cc2097f591d9a09f135 (patch) | |
| tree | bf777353ed2a9b28d8b1577c5f36b68605240375 | |
| parent | c618ade174cc2b4e428457751ad8dd01130c2239 (diff) | |
I am in editing stepped in so far that, should I wade no more, returning were as tedious as go o'er.
| -rw-r--r-- | doc/arithmetic.md | 30 | ||||
| -rw-r--r-- | doc/array.md | 18 | ||||
| -rw-r--r-- | doc/arrayrepr.md | 20 | ||||
| -rw-r--r-- | doc/assert.md | 13 | ||||
| -rw-r--r-- | doc/based.md | 2 | ||||
| -rw-r--r-- | doc/birds.md | 2 | ||||
| -rw-r--r-- | doc/block.md | 56 | ||||
| -rw-r--r-- | doc/choose.md | 8 | ||||
| -rw-r--r-- | doc/compose.md | 6 | ||||
| -rw-r--r-- | docs/doc/arithmetic.html | 23 | ||||
| -rw-r--r-- | docs/doc/array.html | 18 | ||||
| -rw-r--r-- | docs/doc/arrayrepr.html | 20 | ||||
| -rw-r--r-- | docs/doc/assert.html | 19 | ||||
| -rw-r--r-- | docs/doc/based.html | 2 | ||||
| -rw-r--r-- | docs/doc/birds.html | 2 | ||||
| -rw-r--r-- | docs/doc/block.html | 60 | ||||
| -rw-r--r-- | docs/doc/choose.html | 8 | ||||
| -rw-r--r-- | docs/doc/compose.html | 6 |
18 files changed, 181 insertions, 132 deletions
diff --git a/doc/arithmetic.md b/doc/arithmetic.md index c3e17bf8..e51fc53e 100644 --- a/doc/arithmetic.md +++ b/doc/arithmetic.md @@ -16,16 +16,16 @@ Summary of other differences from APL: BQN of course supports the elementary functions taught in schools everywhere: -Symbol | Dyad | Monad --------|----------|------- -`+` | Add | *(Conjugate)* -`-` | Subtract | Negate -`Γ` | Multiply | Sign -`Γ·` | Divide | Reciprocal -`β` | Power | Exponential -`β` | Root | Square root +Symbol | Dyad | Monad | default `π¨` +-------|----------|---------------|:----------: +`+` | Add | *(Conjugate)* | β +`-` | Subtract | Negate | 0 +`Γ` | Multiply | Sign | β +`Γ·` | Divide | Reciprocal | 1 +`β` | Power | Exponential | *e* +`β` | Root | Square root | 2 -The dyadic functions should all be familiar operations, and most likely you are familiar with the symbols `+-ΓΓ·β`. In fact the large `Γ` and `Γ·` might strike you as a regression to early school years, before division was written vertically and multiplication with a simple dot or no symbol at all (BQN reserves the distinction of having no symbol for application and composition). Like these, raising to a power or exponentiation is made regular by giving it the symbol `β`βa true Unicode star and *not* an asterisk. The Root function `β` is also modified to be a binary function, which raises `π©` to the power `Γ·π¨`. In ASCII programming languages `Γ`, `Γ·`, and `β` are often written `*`, `/`, and `^` or `**`. +The dyadic (two-argument) functions should all be familiar operations, and most likely you know the symbols `+-ΓΓ·β`. In fact the large `Γ` and `Γ·` might strike you as a regression to early school years, before division was written vertically and multiplication with a simple dot or no symbol at all. Like these, raising to a power or exponentiation is made regular by giving it the symbol `β`βa true Unicode star and *not* an asterisk. The Root function `β` is also modified to be a binary function, which raises `π©` to the power `Γ·π¨`. In ASCII programming languages `Γ`, `Γ·`, and `β` are often written `*`, `/`, and `^` or `**`. 2 + 3βΏ1βΏ0βΏ5 @@ -39,7 +39,7 @@ The dyadic functions should all be familiar operations, and most likely you are 4 β 81 -Each of these functions also has a meaning with only one argument, although in mathematics only `-` does. The relationship of negation to addition is extended to division (relative to multiplication) as well, so that `Γ·π©` gives the reciprocal `1Γ·π©` of its argument. Power (`β`) is also extended with a default left argument of [Euler's number](https://en.wikipedia.org/wiki/E_(mathematical_constant)) *e*. The default left argument for Root is 2, giving the well-known Square Root. +Each of these functions also has a meaning with only one argument, although mathematics only defines `-` in this way. The relationship of negation to addition is extended to division (relative to multiplication) as well, so that `Γ·π©` gives the reciprocal `1Γ·π©` of its argument. Power (`β`) is also extended with a default left argument of [Euler's number](https://en.wikipedia.org/wiki/E_(mathematical_constant)) *e*. The default left argument for Root is 2, giving the well-known Square Root. - 6 @@ -51,7 +51,7 @@ Each of these functions also has a meaning with only one argument, although in m Take note of the difference between the function `-`, and the "high minus" character `Β―`, which is a part of [numeric notation](syntax.md#constants). Also shown is the number `β`, which BQN supports along with `Β―β` (but depending on implementation BQN may or may not keep track of `Β―0`. Integer optimization loses the distinction so it's best not to rely on it). -The logarithm is written with Undo: `ββΌ`. As with Power, the default base is *e*, giving a natural logarithm. +The logarithm is written with [Undo](undo.md): `ββΌ`. As with Power, the default base is *e*, giving a natural logarithm. ββΌ 10 @@ -122,7 +122,7 @@ Now the monadic function symbols resemble those used in mathematics. In the case | Β―ββΏΒ―6βΏ0βΏ2 -Floor (`β`) returns the largest integer less than or equal to the argument, and Ceiling (`β`) returns the smallest one greater than or equal to it. For this purpose `Β―β` and `β` are treated as integers, so that the floor or ceiling of an infinity is itself. Absolute value removes the argument's sign by negating it if it is less than 0, so that its result is always non-negative. +Floor (`β`) returns the largest integer less than or equal to the argument, and Ceiling (`β`) returns the smallest one greater than or equal to it. For this purpose `Β―β` and `β` are treated as integers, so that the floor or ceiling of an infinity is itself. Absolute value removes the sign of `π©` by negating it if it's less than 0, so that its result is always non-negative. Minimum (`β`) returns the smaller of its two arguments, and Maximum (`β`) returns the larger. These functions are loosely related to Floor and Ceiling in their use of comparison, and can be defined similarly: for example, the minimum of two numbers is the largest number less than or equal to both of them. To take the minimum or maximum of an entire list, use a [fold](fold.md). @@ -130,7 +130,7 @@ Minimum (`β`) returns the smaller of its two arguments, and Maximum (`β`) re β½βΈβ β8 -Modulus (`|`) is similar to the modular division operation written `%` in C-like languages, but it takes the arguments in the opposite order, and differs in its handling of negative arguments. It's defined to be `{π©-π¨Γβπ©Γ·π¨}`, except that the multiplication should always return 0 if its right argument is 0, even if `π¨` is infinite. +Modulus (`|`) is similar to the modular division operation written `%` in C-like languages, but it takes the arguments in the opposite order, and differs in its handling of negative arguments. It's the same computation as `{π©-π¨Γβπ©Γ·π¨}` but probably has better precision. 3 | β8 @@ -171,11 +171,11 @@ Arithmetic primitives act as though they are given [depth](depth.md#the-depth-mo Γ βΛβ¨Β―8,Β―9β©βΏβ¨β¨2,0β©,4,5β© -With two arguments many combinations are possible. Arrays of equal shape are matched element-wise, and an atom is matched to every element of an array. +With two arguments, many combinations are possible. Arrays of equal shape are matched element-wise, and an atom is matched to every element of an array. 10βΏ20βΏ30 + 5βΏ6βΏ7 - 10 Γ 4βΏ3βΏ2β6βΏ7βΏ8 + 10 Γ [4βΏ3βΏ2,6βΏ7βΏ8] Arrays with different ranks can also be paired: they are matched by [leading axis agreement](leading.md#leading-axis-agreement). This means that one shape must be a prefix of the other, and elements of the lower-rank array are repeated to match up with cells of the higher-rank one. diff --git a/doc/array.md b/doc/array.md index 873778c9..19fe7fe7 100644 --- a/doc/array.md +++ b/doc/array.md @@ -6,9 +6,9 @@ As BQN is an array language, it's often helpful to understand what an array is w In BQN, as in APL, arrays are multidimensional, instead of strictly linear. Languages like Python, Javascript, or Haskell offer only one-dimensional arrays with `[]` syntax, and typically represent multidimensional data with nested arrays. Multidimensional arrays have fundamental differences relative to this model. -BQN's arrays are immutable, meaning that an array is entirely defined by its attributes, and there is no way to modify an existing array, only to produce another array that has changes relative to it. As a result, an array can never contain itself, and arrays form an inductive type. BQN's [mutable](lexical.md#mutation) types are operations and namespaces. +BQN's arrays are immutable, meaning that an array is entirely defined by its attributes, and there's no way to modify an existing array, only to produce another array that has changes relative to it. As a result, an array can never contain itself. BQN's [mutable](lexical.md#mutation) types are operations and namespaces. -An array might also have a [fill element](fill.md) that captures some structural information about its elements and is used by a few operations. The fill, as an inferred property, isn't considered to truly be part of the array but is instead some information about the array that the interpreter keeps track of. So it's out of scope here. +An array might also have a [fill element](fill.md) that captures some structural information about its elements and is used by a few operations. As an inferred property, the fill isn't considered to truly be part of the array, but is instead some information about it that the interpreter keeps track of. So it's out of scope here. <!--GEN xt β βΎΛ Highlightββ’ReprΒ¨ xv β 3βΏ2βΏ6β₯ΓΛ2+3Γβ5 @@ -87,7 +87,7 @@ The array also needs to be complete. Every elementβevery combination of positi ## Ordering and indices -To finish this definition of an array we also need to nail down the idea of a position. The positions along one dimension can't be labelled in any way, but they have a linear ordering (mathematically speaking, a [total order](https://en.wikipedia.org/wiki/Total_order): out of any two different positions one comes earlier and the other later). BQN keeps track of this order: for example, when we [join](join.md) two arrays it places positions in `π¨` before those of `π©` and otherwise maintains the original ordering. +To finish this definition of an array we also need to nail down the idea of a position. The positions along one dimension can't have labels attached to them, but they have a linear ordering (mathematically speaking, a [total order](https://en.wikipedia.org/wiki/Total_order): out of any two different positions one comes earlier and the other later). BQN keeps track of this order: for example, when we [join](join.md) two arrays it places positions in `π¨` before those of `π©` and otherwise maintains the original orderings. "before" βΎ "after" @@ -103,19 +103,19 @@ The total number of elements in an array is its **bound**, and can be found usin ## Elements -Any BQN value can be used as an array element, including another array (BQN, as a dynamically-typed language, doesn't restrict the types that can be used in one context without a good reason). However, BQN arrays are restricted relative to other array models. Frameworks like NumPy or Julia have mutable arrays, so that the value of an element can be changed after the array is created. This allows an array to be its own element, by creating an array and then inserting it into itself. This would be unnatural in BQN, where an array can only be formed from elements that already exist. In BQN only operations and namespaces are [mutable](lexical.md#mutation). +Any BQN value can be used as an array element, including another array (BQN, as a dynamically-typed language, doesn't restrict the types that can be used in one context without a good reason). However, BQN arrays are in some sense restricted relative to other array models. Frameworks like NumPy or Julia have mutable arrays, so that the value of an element can be changed after the array is created. This allows an array to be its own element, by creating an array and then inserting it into itself. This would be unnatural in BQN, where an array can only be formed from elements that already exist. In BQN only operations and namespaces are [mutable](lexical.md#mutation). -An array with no elements (a bound of 0) is called **empty**. These arrays can cause problems when a property should be computed from the elements of an array, like the sum `+Β΄π©` or shape of the [merged](couple.md#merge-and-array-theory) array `>π©`. BQN has two mechanisms to make these cases work better. First, reductions like `+Β΄` have [identity values](fold.md#identity-values) for certain functions, so that `+Β΄β¨β©` is `0` for example. Second, every array might have a [fill element](fill.md), a special "typical element" for the array. Functions like Merge use this element's structure to determine the result shape when there are no actual elements to be used. +An array with no elements (a bound of 0) is called **empty**. These arrays can cause problems when a property should be computed from the elements of an array, like the sum `+Β΄π©` or shape of the [merged](couple.md#merge-and-array-theory) array `>π©`. BQN has two mechanisms to make these cases work better. First, Fold (`Β΄`) and Insert (`Λ`) have [identity values](fold.md#identity-values) for certain functions, so that `+Β΄β¨β©` is `0` for example. Second, every array might have a [fill element](fill.md), a special "typical element" for the array. Functions like Merge use this element's structure to determine the result shape when there are no actual elements to be used. ## Cells -The contents of an array are its elements, but it also makes sense to split up an array into subarrays of elements called cells. The most important kind of cell, a **major cell** consists of all the elements that have indices beginning with some particular index `i`. For this to make sense, `i` must be between `0` and the length `l` of the array's first axis, so that there are `l` major cells each identified by an index. +The contents of an array are its elements, but it also makes sense to split up an array into subarrays of elements called cells. The most important kind of cell, a **major cell**, consists of all the elements whose indices begin with some particular index `i`. For this to make sense, `i` must be between `0` and the length `n` of the array's first axis, so that there are `n` major cells each identified by an index. 2βΏ3βΏ4 Γβ 1βΏ5βΏ8βΏ11 1 β 2βΏ3βΏ4 Γβ 1βΏ5βΏ8βΏ11 # Major cell 1 -A major cell still has an array structure: it retains all the axes of the original array other than the first. So it has its own major cells, identified by the index `i` of the original major cell and `j` within it. These are also cells of the original array. Generalizing, a **cell** with index list `l` is defined to be the array of all elements whose indices begin with `l`. In an array with rank `n`, the cell rank is `n-β l`, and cells grouped using this rank. An `n`-cell mst have an empty cell index, so that it includes all elementsβit's the entire array! An `n-1` cell, also called a Β―1-cell, is a major cell. A 0-cell has an index of length `n`, and contains a single element. +A major cell still has an array structure: it retains all the axes of the original array other than the first. So it has its own major cells, identified by the index `i` of the original major cell and `j` within it. These are also cells of the original array. Generalizing, a **cell** with index list `l` is defined to be the array of all elements whose indices begin with `l`. In an array with rank `r`, the cell rank is `r-β l`, and cells grouped using this rank. An `r`-cell must have an empty cell index, so that it includes all elementsβit's the entire array! An `r-1` cell, also called a Β―1-cell, is a major cell. A 0-cell has an index of length `r`, and contains a single element. Cells are the center of the [leading axis model](leading.md) used to structure many array primitives. @@ -123,9 +123,9 @@ Cells are the center of the [leading axis model](leading.md) used to structure m Summarizing, the values needed to define an array are its rank (the number of axes), its shape (the number of positions along each axis), and the value of each element (that is, at each combination of positions). Two arrays [match](match.md) when all these values match. -If the rank is considered to be part of the shape, as it is when the shape is a BQN list, then the array is defined by its shape and element listβfrom [deshape](reshape.md). +If the rank is considered to be part of the shape, as it is when the shape is a BQN list, then the array is defined by its shape, and element list as returned by [deshape](reshape.md). -Here's a somewhat informal mathematical take. Given a set of possible element values `T`, a *list* of `T` of length `l` is a map from natural numbers less than `l` to `T`. An array is a rank `r`, along with a list `s` of natural numbers of length `r`, and a map from lists of natural numbers `i` that satisfy `i(j) < s(j)` for all natural numbers `j<r` to BQN values. Arrays are an inductive type, so that an array can only be defined using elements that already exist. As a result an array's elements are always values of lesser complexity and selecting one element of an array, then an element of that element, and so on, must eventually reach a non-array. +Here's a somewhat informal mathematical take. Given a set of possible element values `T`, a *list* of `T` of length `l` is a map from natural numbers less than `l` to `T`. An array is a rank `r`, along with a list `s` of natural numbers of length `r`, and a map from lists of natural numbers `i` that satisfy `i(j) < s(j)` for all natural numbers `j<r` to BQN values. Arrays are an inductive type, so that an array can only be defined using elements that already exist. As a result, an array's elements are always values of lesser complexity than it: selecting one element of an array, then an element of that element, and so on, must eventually reach a non-array. ## Why arrays? diff --git a/doc/arrayrepr.md b/doc/arrayrepr.md index ca2f3f86..205c4a44 100644 --- a/doc/arrayrepr.md +++ b/doc/arrayrepr.md @@ -2,13 +2,13 @@ # Array notation and display -This page documents ways arrays are represented in BQN: the notation you can use to write them and the way the REPL displays them. +This page documents ways [arrays](array.md) are represented in BQN: the notation you can use to write them and the way the REPL displays them. Array display is a feature of a BQN environment such as a REPL. You can also access it with `β’Fmt`, which takes a value and returns a string indicating how it would be formatted. Array notation is of course part of BQN source code, but you can also go from an array to one possible source code for it using the similar system function `β’Repr`. ## Array display -Although it's really part of the language environment and not BQN itself, let's look at display first so it's clear what arrays we're talking about later on. The BQN REPL prints arrays in a way that's meant to unambiguously show the structure and data, but doesn't correspond to BQN source code. A few examples are given below; of course, displays like this appear all over the documentation. +Although it's really part of the language environment and not BQN itself, let's look at display first so it's clear what arrays we're talking about later on. A BQN session prints arrays in a way that's meant to unambiguously show the structure and data, but doesn't correspond to BQN source code. A few examples are given below; of course, displays like this appear all over the documentation. β 3βΏ4 # Array of lists @@ -26,7 +26,7 @@ Those top-left and bottom-right corners are a distinctive part of BQN's display, β¨2,"xy"β©ββ¨2βΏ2β₯"abcd",4β© # Nested 2Γ2 array -The lack of extra separation is to make it clear that the corners enclose the array rather than any of its elements (elements are still distinguishable becase an individual element won't contain whitespace except maybe between quotes). Now every set of corners indicates one array. This is a good fit for the [based array model](based.md), where data doesn't have to be in an array. +The lack of extra separation is to make it clear that the corners enclose the whole array rather than any of its elements (elements are still distinguishable becase an individual element won't contain whitespace, except maybe between quotes). Every set of corners indicates one array. This is a good fit for the [based array model](based.md), where data doesn't have to be in an array. #### Rank indicator @@ -58,7 +58,7 @@ The pattern continues: 3-cells are separated by 2 spaces, 4-cells by 3, and so o #### Empty arrays -The top-left corner can show the rank of an array but not its shape; the shape must be seen from the data. An empty array has no data, and it's hard to tell shape from a bunch of blank space. In general, an empty array is printed as `βshape`. An empty list is shown using brackets `β¨β©`, which are discussed in the next section. +The top-left corner can show the rank of an array but not its shape; the shape must be seen from the data. An empty array has no data, and it can be impossible to tell shape from a bunch of blank space. So an empty array is usually printed as `βshape`. An empty list is shown using brackets `β¨β©`, which are discussed in the next section. βΒ¨ β¨0βΏ4, 3βΏ0βΏ1, 2βΏ0βΏ0, 0β© @@ -82,13 +82,13 @@ The second is for lists with simple enough elements, which are displayed on one "" -This case also covers empty lists, which are shown as `β¨β©`. This includes an empty string, as the only difference between an empty string and any other empty list is its fill element and array displays don't depend on the fill. +This case also covers empty lists, which are shown as `β¨β©`. This includes an empty string: the only difference between an empty string and any other empty list is its fill element, and array displays don't depend on the fill. ## Array literals *The tutorial section [here](../tutorial/list.md#list-notation) also covers this topic.* -There are three kinds literal notation for lists: strings, list notation, and stranding. Strings indicate character lists (with space for the [fill](fill.md)) and the other two can combine any sequence of elements. Additionally, there's a square bracket notation that can form higher-rank arrays. +Now it's time to discuss ways to write arrays in a BQN program. There are three kinds literal notation for lists: strings, list notation, and stranding. Strings indicate character lists (with space for the [fill](fill.md)) and the other two can combine any sequence of elements. Additionally, there's a square bracket notation that can form higher-rank arrays. ### Strings @@ -104,11 +104,11 @@ Even special characters like a newline can appear in a string literal, so that s **List notation** uses angle brackets `β¨β©`. The contents are structurally identical to those of a [block](block.md), that is, a list of expressions [separated](syntax.md#separators) by `,` or `β` or newlines. Unlike a block, a list doesn't need to have any expressions: `β¨β©` or `β¨ββ©` or `β¨,,β,β©` will create an empty list. Other differences are that a list doesn't introduce a new [scope](lexical.md) and all of the expressions have to result in a value, not [Nothing](expression.md#nothing) (`Β·`). -Entries in a list are evaluated in source order, and the value will be the list of those results. The list has a subject role, even if it contains expressions with other roles. Any value can be an element. +Entries in a list are evaluated in source order, and the value will be the list of those results. The list has a subject [role](expression.md#syntactic-role), even if it contains expressions with other roles. Any value can be an element. β¨@, βΛ, β"abc"β© -BQN's separator rules give list notation a very flexible structure. You can put all the elements on one line or spread them across lines, with the option of adding blank lines between elements. A separator at the end of a line is never needed but leading and trailing separators are allowed. +BQN's separator rules give list notation a very flexible structure. You can put all the elements on one line or spread them across lines, with the option of adding blank lines between elements. A separator at the end of a line is never needed, but leading and trailing separators are allowed. β¨ "e0", "e1" @@ -127,11 +127,11 @@ Higher-rank arrays can be written with `[]`, an **array notation** that indicate [2βΏ3, 4βΏ1, 0βΏ5] -This syntax doesn't work for creating rank 0 arraysβuse [Enclose](enclose.md) `<` for theseβor empty arrays. The notation `[]` would be ambiguous, so it's not allowed (although it can be used for destructuring, which works with an existing array). To create a specific empty array, [Reshape](reshape.md) (`β₯`) is probably the best approach. +This syntax doesn't work for creating rank 0 arraysβuse [Enclose](enclose.md) `<` for theseβor empty arrays. The notation `[]` would be ambiguous, so it's not allowed (although it can be used for destructuring, which works with an existing array). To create an empty array with a specific shape, [Reshape](reshape.md) (`β₯`) is probably the best approach. ### Strands -**Strand notation** is another way to write lists of length two or more. The elements are connected with the ligature character `βΏ`. It has a precedence lower than the [namespace](namespace.md) dot but higher than anything else other than paired brackets `()`, `{}`, and `β¨β©`, so compound elements generally need to be placed in parentheses. Expressions joined by ligatures behave exactly the same as those in list notation: they are evaluated in order and placed in a list. +**Strand notation** is another way to write lists of length two or more. The elements are connected with the ligature character `βΏ`. It has a precedence higher than anything else other than the [namespace](namespace.md) dot `.` and of course paired brackets `()`, `{}`, and `β¨β©`. This means complicated elements generally need to be placed in parentheses. Expressions joined by ligatures behave exactly the same as those in list notation: they are evaluated in order and placed in a list. +βΏΒ΄βΏββΏΓ diff --git a/doc/assert.md b/doc/assert.md index 14e4cf72..83d8570c 100644 --- a/doc/assert.md +++ b/doc/assert.md @@ -9,23 +9,30 @@ BQN provides some simple facilities for dealing with errors. Errors are an unusu BQN takes the position that errors exist to indicate exceptional conditions that the developer of a given program didn't expect. However, the types of errors that BQN naturally checks for, such as mismatched shapes in Couple (`β`), aren't always enough to detect exceptional conditions. Issues like numeric values that don't make physical sense will slip right through. BQN makes it easy for a programmer to check for these sorts of problems by building in the primitive Assert, written `!`. This function checks whether `π©` matches `1`: if it does, then it does nothing and returns `π©`, and otherwise it gives an error. ! 2=2 # Passed + ! 2=3 # Failed To pass, the right argument must be exactly the number `1`; any other value causes an error. For example, an array of `1`s still causes an error; use `β§Β΄β₯` to convert a boolean array to a single boolean that indicates whether all of its values are true. ! (β§=β¨βΎΒ¬)βΛ β2 + ! β§Β΄β₯ (β§=β¨βΎΒ¬)βΛ β2 -Assert can take a left argument, which gives a message to be associated with the error. It's typical to use a string for the left argument in order to display it to the programmer, but the left argument can be any value. +Assert can take a left argument, which gives a message to be associated with the error. It's typical to use a string for `π¨` in order to display it to the programmer, but `π¨` can be any value. "Message" ! 0 + β¨β,"abc",Λβ© ! '0' +In the 1-argument case, `π©` is used for the error message if it's not `1`. So an unconditional error can also be written this way: + + ! "Message" + ### Computing the error message on demand Because the left argument to a function is always computed before the function is called, Assert [doesn't let you](../commentary/problems.md#assert-has-no-way-to-compute-the-error-message) compute the error message only if there's an error. This might be a problem if the error message computation is slow or has side effects. There are a few ways to work around the issue: -- Handle errors with ordinary if-then logic (perhaps using [control structures](control.md)). This is probably the best path for user-facing applications where displaying an error goes through the user interface. -- Write a function `Message` to compute the message, and call `π¨ MessageβΈ!β(1βΈβ’) π©` or similar instead of `!`. +- Handle bad inputs with ordinary if-then logic (perhaps using [control structures](control.md)), not errors. This is probably the best path for user-facing applications where BQN's normal error display isn't wanted. +- Write a function `Message` to compute the message, and call `!βMessageβ(1βΈβ’) π©` or similar instead of `!`. - If the error will be caught elsewhere in the program, use a closure for the message and evaluate it when caught. With a function `Message` as above, `message ! π©` works, and `{β¦}ΛβΈ! π©` is a convenient syntax for block functions. ## Catch diff --git a/doc/based.md b/doc/based.md index f7bd2431..26c8b212 100644 --- a/doc/based.md +++ b/doc/based.md @@ -16,7 +16,7 @@ If you're an array programmer then I have bad news for you. My thesis here is th APL tends to define its data by starting with the array and then looking downwards in depth at what it contains. The based array model, as the name suggests, starts at the foundations, which in BQN are called "atoms". There are six [types](types.md) of atom, which together with the array type give the seven types a value can have in BQN. Based means being yourself, and an atom's *not* an array. -An atom has [depth](depth.md) 0, and doesn't inherently have a shape. However, primitives that expect an array promote atoms by [enclosing](enclose.md) them to get a rank-0, or *unit*, array that contains the atom (any value can be enclosed in this way, giving a unit array with higher depth, but it only happens automatically for atoms). [Rank and shape](shape.md) both do this, so an atom can be considered to have the same dimensions as a unit array: rank 0 and shape `β¨β©`. An atom is also considered a kind of unit, but it's not a unit array. +An atom has [depth](depth.md) 0, and doesn't inherently have a shape. However, primitives that expect an array will promote an atom by [enclosing](enclose.md) to get a rank-0, or *unit*, array that contains it (any value can be enclosed in this way, giving a unit array with higher depth, but it only happens automatically for atoms). [Rank and shape](shape.md) both do this, so an atom can be considered to have the same dimensions as a unit array: rank 0 and shape `β¨β©`. An atom is also considered a kind of unit, but it's not a unit array. Atoms are displayed as plain values, while enclosed atoms, that is, depth-1 unit arrays, are shown with an array display. diff --git a/doc/birds.md b/doc/birds.md index 71a59d3b..77811bf8 100644 --- a/doc/birds.md +++ b/doc/birds.md @@ -2,7 +2,7 @@ # BQN for birdwatchers -Some people consider it reasonable to name [combinators](primitive.md#modifiers) after types of birds. [Here's](https://blog.lahteenmaki.net/combinator-birds.html) one compendium of such names, and [another](https://wiki.xxiivv.com/site/ornithodex.html) that lacks its obsessive completeness but makes up for it with rambling accounts of imagined forests. There is something wrong with these people. Some of these birds are not even real. "Quixotic bird"? Have you not heard of a quail? Nonetheless, I don't judge such afflicted souls (certainly not publicly), and have provided this translation table to explain BQN in terms they can understand. +Some people consider it reasonable to name [combinators](primitive.md#modifiers) after types of birds. [Here's](https://blog.lahteenmaki.net/combinator-birds.html) one compendium of such names, and [another](https://wiki.xxiivv.com/site/ornithodex.html) that lacks its obsessive completeness but makes up for it with [rambling accounts](https://wiki.xxiivv.com/site/logic.html) of imagined forests. There is something wrong with these people. Some of these birds are not even real. "Quixotic bird"? Have you not heard of a quail? Nonetheless, I don't judge such afflicted souls (certainly not publicly), and have provided this translation table to explain BQN in terms they can understand. | BQN | Bird 1 | 1 | Bird 2 | 2 | | :-----: | -------- | -------- | ------------ | ------------------------------ | diff --git a/doc/block.md b/doc/block.md index 8cdaed9c..823007f1 100644 --- a/doc/block.md +++ b/doc/block.md @@ -2,14 +2,16 @@ # Blocks -In BQN, a *block* is any piece of code surrounded with curly braces `{}`. Blocks can be used simply to group statements, or can define functions or modifiers. They are the sole large-scale structure used to organize programs. An important aspect of organization is [namespaces](namespace.md), which are created with blocks but not discussed on this page. +In BQN, a *block* is any piece of code surrounded with curly braces `{}`. Blocks can be used simply to group statements, or can define functions or modifiers. They are the sole large-scale structure used to organize programs. One organizing tool not discussed here is [namespaces](namespace.md), which are created with blocks but have their own page. Programming without blocks (only recommended at the small scale) is called [tacit](tacit.md) programming. Blocks are most commonly used to define functions by including one of the special names for arguments, `π¨` or `π©`. With the operands `π½` or `πΎ`, they can also define 1-modifiers or 2-modifiers. {π©+1} 3 Γ{π©π½π©} 4 -Because they use [lexical scoping](lexical.md), blocks can also be used to encapsulate code. If a block uses only variables that it initializes, then it has no dependence on its environment and would work the same way if defined anywhere. But it can also use external variables, defined in a containing block. +A block [header](#block-headers) is written before a `:` and describes the block type, and what inputs it accepts. A block can be split into [multiple bodies](#multiple-bodies) using `;`s, so that each handles different cases. A [predicate](#predicates), written with `?`, can test an arbitrary condition to refine these cases. + +Because they use [lexical scoping](lexical.md), blocks also encapsulate code. If a block uses only variables that it initializes, then it has no dependence on its environment and would work the same way if defined anywhere. But it can also use external variables, defined in a containing block. aβbβ"outer" { aβ"inner" β aβΏb } @@ -21,7 +23,7 @@ In the simplest case a block is just a list of statements, which are executed to updown β { upββ5 β downββ½up β upβΎdown } updown -An immediate block is only ever evaluated once, and can't be used for control flow in a program. Including special names in a headerless block lets us define functions and modifiers, which have a broader range of uses. All special names are listed below: +An immediate block is only ever evaluated once, and can't be used for control flow in a program. Special names can be used to define [functions and modifiers](ops.md), which have a broader range of uses. All special names are listed below: | Lowercase | Uppercase | Meaning |-----------|-----------|--------- @@ -32,27 +34,30 @@ An immediate block is only ever evaluated once, and can't be used for control fl | `π` | `πΎ` | Right [operand](#operands) | `π£` | none | Modifier [self-reference](#self-reference) -Of these, `π£` is sort of a "more special" character, as we'll discuss below. Except for `π£`, every special name is a single character and can't have underscores added to spell it as a modifier. This allows a modifier to be applied to a special name with no spacing, as in `π_m`, where it couldn't be with ordinary names. +Most special names have a lowercase form for a subject [role](expression.md#syntactic-role) and uppercase for a function role. But `π£` is sort of a "more special" character, as we'll discuss below. The special names other than `π£` are single characters that don't attach to other letters, allowing `π½π©` or `π_m` to work without spaces; `π£` is always modifier-valued, so it ought to attach to underscores. ### Arguments The names `π¨` and `π©`, and their uppercase spellings, represent function arguments. As the argument to a function is typically data, it's more common to use the lowercase forms for these. Having either of these names turns an immediate block into a function (or an immediate modifier into a deferred one; see the next section). Instead of being evaluated as soon as it appears in the source, a function is evaluated when it's called, with the special names set to appropriate values. Their values can be changed like ordinary variables. {'c'=π©} "abcd" + { π©+β©2 β 0βπ© } 3 - 4 { β¨π©β-π¨β© } 5 + + 4 { β¨π©,-π¨β© } 5 A function with `π¨` in its definition doesn't have to be called with two arguments. If it has only one, then `π¨` is given the special value [Nothing](expression.md#nothing), or `Β·`. This is the only time a variable can ever be Nothing, as an assignment such as `vβΒ·` is not allowed. 3 { (2Γπ¨)-π© } 1 { (2Γπ¨)-π© } 1 -In the second function, `π¨` behaves just like `Β·`, so that the function `2Γπ¨` is not evaluated and `-` doesn't have a left argument. It has a similar effect when used as the left argument to a function in a train. +In the second function, `π¨` behaves just like `Β·`, so that the function `2Γπ¨` is not evaluated and `-` doesn't have a left argument. It has a similar effect when used as the left argument to a function in a [train](train.md). "abc" { (π¨ββ½) π© } "def" { (π¨ββ½) π© } "def" -However, `Β·` can only be used as an argument, and not a list element or operand. Don't use `π¨` in these ways in a function that could be called monadically. Another potential issue is that `βΈ` and `β` don't work the way you might expect. +However, `Β·` can only be used as an argument, and not a list element or operand. Don't use `π¨` in these ways in a function that could be called monadically. Another [potential issue](../problems.md#nothing--interacts-strangely-with-before-and-after) is that `βΈ` and `β` don't work the way you might expect. + { π¨ ββΈ- π© } 5 @@ -79,22 +84,22 @@ The distinction between an immediate and deferred modifier only matters inside t ### Self-reference -If a block is assigned a name after it is created, this name can be used for recursion: +If a block is assigned a name after it's created, this name can be used for recursion: Fact β { π© Γ (0βΈ<)βΆ1βΏFact π©-1 } Fact 7 (ΓΒ΄1+β) 7 # There's often a simpler solution than recursion -This is somewhat unsatisfying because it is external to the function being defined, even though it doesn't depend on outside information. Instead, the special name `π` can be used to refer to the function it appears in. This allows anonymous recursive functions to be defined. +This is somewhat unsatisfying because the name is external to the function being defined, but the definition shouldn't depend on outside information. Instead, the special name `π` can be used to refer to the function it appears in. This allows anonymous recursive functions to be defined. { π© Γ (0βΈ<)βΆ1βΏπ π©-1 } 7 -For modifiers, `π£` refers to the containing modifier. `π` makes the modifier a deferred modifier like `π¨` and `π©` do, and refers to the derived function. For example, this tail-recursive factorial function uses the operand to accumulate a result, a task that is usually done with a second `factorial_helper` function in elementary Scheme. +For modifiers, `π£` refers to the containing modifier. `π` makes the modifier a deferred modifier like `π¨` and `π©` do, and refers to the derived function. For example, this tail-recursive factorial function uses the operand to accumulate a result, a task that's usually done with a second `factorial_helper` function in elementary Scheme (BQN doesn't optimize tail recursion though; it's just shown here as an example). Fact_mod β 1 { (0βΈ<)βΆβ¨π, (πΓπ©)_π£β© π©-1 } Fact_mod 7 -Because `π£` only ever refers to a 1-modifier or 2-modifer, it can never make sense to refer to it as a function, and the uppercase letter `β` is not recognized by BQN. In order to allow `π£` to be spelled as a 1-modifier `_π£` or 2-modifier `_π£_`, it is treated as an ordinary identifier character, so it must be separated from letters or numbers by spaces. +Because `π£` only ever refers to a 1-modifier or 2-modifer, it can never make sense to refer to it as a function, and the uppercase letter `β` is not recognized by BQN. To allow `π£` to be spelled as a 1-modifier `_π£` or 2-modifier `_π£_`, it's tokenized as an ordinary identifier character, so it has to be separated from adjacent letters or numbers with a space. ## Block headers @@ -122,7 +127,7 @@ Its syntax mirrors an application of the block. As suggested by the positioning, { F _op_ Β·βΏval: β¦ -In all cases special names still work just like in a headerless function. In this respect the effect of the header is the same as a series of assignments at the beginning of a function, such as the following translation of the second header above: +In all cases special names still work just like in a headerless function. In this respect, the effect of the header is the same as a series of assignments at the beginning of a function, such as the following translation of the second header above: { # Fn _apply β¨a,bβ©: Fn β π½ @@ -130,15 +135,17 @@ In all cases special names still work just like in a headerless function. In thi β¨a,bβ© β π© β¦ -Unlike these assignments, the header also constrains what inputs the block can take: a monadic 1-modifier like the one above can't take a right operand or left argument, and consequently its body can't contain `πΎ` or `π¨`. Calling it with a left argument, or a right argument that isn't a two-element list, will result in an error. +Unlike these assignments, the header also constrains what inputs the block can take: a monadic 1-modifier like the one above can't take a right operand or left argument, so its body can't contain `πΎ` or `π¨`. Calling it with a left argument, or a right argument that isn't a two-element list, will result in an error. ### Destructuring -Arguments and operands allow [destructuring](expression.md#destructuring) like assignment does. While assignment only tolerates lists of variables, header destructuring also allows constants. The argument must match the given structure, including the constants where they appear, or an error results. +Arguments and operands allow [destructuring](expression.md#destructuring) like assignment does. While assignment only tolerates lists of variables, header destructuring also allows constants. For the header to match, the argument must share the given structure, including the constants where they appear. Destruct β { π aβΏ1βΏβ¨b,Β·,2β©: aβb } Destruct 5βΏ1βΏβ¨7,Ο,2β© +It's also worth noting here that `[]` is a valid destructuring target, matching any length-0 array, even though it can't be used as a value since it's ambiguous. This syntax is also allowed in regular destructuring, but it's not very useful in that case. + ### Special names in headers Any element of a function or modifier header can be left nameless by using the corresponding special name in that position, instead of an identifier. For example, the header `π¨ π½_π£_πΎ π©:` incorporates as much vagueness as possible. It indicates a deferred 2-modifier, but provides no other information. @@ -154,21 +161,26 @@ A header can also be a plain name with no inputs, called a *label*. A label spec { _π£: # 1-Modifier { _π£_: # 2-Modifier -For immediate blocks, this is the only type of header possible, and it must use an identifier as there is no applicable special name. However, the name can't be used in code: it doesn't make sense to refer to a value while it is still being computed! +For immediate blocks, this is the only type of header possible, and it must use an identifier as there's no applicable special name. However, the name can't be used in code: it doesn't make sense to refer to a value while it's still being computed! ## Multiple bodies -Blocks can include more than one body, separated by semicolons `;`. The body used for a particular evaluation is chosen based on the arguments the the block. One special case is that functions and deferred modifiers can have two headerless bodies (that is, no headers or predicatesβsee below): the first applies when there's one argument and the second when there are two. +Blocks can include more than one body, separated by semicolons `;`. The body used for a particular evaluation is chosen based on the inputs to the block. One special case is that functions and deferred modifiers can have two headerless bodies (that is, no headers or [predicates](#predicates)): the first applies when there's one argument and the second when there are two. Ambiv β { β¨1,π©β© ; β¨2,π¨,π©β© } + Ambiv 'a' + 'a' Ambiv 'b' Bodies with headers come before any that don't have them. When a block is called, its headers are checked in order for compatibility with the arguments, and the first body with a compatible header is used. CaseAdd β { 2π3:0βΏ5 ; 2ππ©:β¨1,2+π©β© ; ππ©:2βΏπ© } + 2 CaseAdd 3 + 2 CaseAdd 4 + CaseAdd 4 If no header is compatible, the call results in an error. @@ -190,25 +202,29 @@ These case-style headers function exactly the same as if they were preceded by ` ### Predicates -Destructuring with a header is quite limited, only allowing matching structure and data with exact equality. A predicate, written with `?`, allows you to test an arbitrary property before evaluating the rest of the body, and also serves as a limited kind of control flow. It can be thought of as an extension to a header, so that for example the following function requires the argument to have two elements and for the first to be less than the second before using the first body. Otherwise it moves to the next body, which is unconditional. +Destructuring with a header is limited, as it can only match a particular structure or value exactlyβnot, for example, a range of lengths. A predicate, written with `?`, allows you to test an arbitrary property before evaluating the rest of the body, and also serves as a limited kind of control flow. It can be thought of as an extension to a header. So the following function requires the argument to have two elements and for the first to be less than the second before using the first body. Otherwise it moves to the next body, which is unconditional. CheckPair β { πβ¨a,bβ©: a<b? "ok" ; "not ok" } CheckPair β¨3,8β© # Fails destructuring + CheckPair β¨1,4,5β© # Not a pair + CheckPair β¨3,Β―1β© # Not ascending -The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. In fact, `?` functions just like a separator (like `β` or `,`) with a side effect. +The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. Really, `?` works just like a separator (like `β` or `,`) with a side effect. { rββ½π© β 't'=βr ? r ; π© }Β¨ "test"βΏ"this" -So `r` is the reversed argument, and if its first character (the last one in `π©`) is `'t'` then it returns `r`, and otherwise we abandon that line of reasoning and return `π©`. This sounds a lot like an if statement. And `{ a<b ? a ; b }`, which computes `aβb` the hard way, shows how the syntax can be similar to a ternary operator. This is an immediate block with multiple bodies, something that makes sense with predicates but not headers. But `?;` offers more possibilities. It can support any number of options, with multiple tests for each oneβthe structure below is "if \_ and \_ then \_; else if \_ then \_; else \_". +So `r` is the reversed argument, and if its first character (the last one in `π©`) is `'t'` then it returns `r`, and otherwise we abandon that line of reasoning and return `π©`. + +This sounds a lot like an if statement. And `{ a<b ? a ; b }`, which computes `aβb` the hard way, shows how the syntax can be similar to a ternary operator. This is an immediate block with multiple bodies, something that makes sense with predicates but not headers. But `?;` offers more possibilities. It can support any number of options, with multiple tests for each oneβthe structure below is "if \_ and \_ then \_; else if \_ then \_; else \_". Thing β { π©β₯3? π©β€8? 2|π© ; π©=0? @ ; β } (β’ β ThingΒ¨) β10 # Table of arguments and results -This structure is still constrained by the rules of block bodies: each instance of `;` is a separate scope, so that variables defined before a `?` don't survive past the `;`. +This structure is still controlled by the rules of block bodies: each instance of `;` is a separate scope, so that variables defined before a `?` don't survive past the `;`. { 0=nββ π© ? β ; n } "abc" diff --git a/doc/choose.md b/doc/choose.md index 4362b9f5..7d53a122 100644 --- a/doc/choose.md +++ b/doc/choose.md @@ -2,17 +2,17 @@ # Choose -The 2-modifier Choose (`βΆ`) applies one function from a list `π`, based on a selection function `π½` that returns an index. It's a combinator form of [Pick](pick.md) (`β`), so that `{fβ(π¨π½π©)βπ β π¨Fπ©}` is a complete definition. For example, the function below subtracts 1 from an argument if negative and adds 1 if positive. +The 2-modifier Choose (`βΆ`) applies one function from a list `π`, based on the selecting index returned by a function `π½`. It's a combinator form of [Pick](pick.md) (`β`), so that `{fβ(π¨π½π©)βπ β π¨Fπ©}` is a complete definition. For example, the function below subtracts 1 from its argument if negative and adds 1 if positive. 0βΈβ€βΆβ¨-β1, +β1β©Β¨ 3βΏΒ―1βΏ5 -Here the selection function `π½` is `0βΈβ€`, while `π` is a list of two functions `β¨-β1, +β1β©`. On the first argument, `3`, `π½3` is `0β€3`, or `1`, so the function `+β1` from `π` is chosen. The use of array indices means "false" comes first in `π` and "true" comes second, which is backwards relative to if-else constructs in most programming languages (including BQN's own predicates). When using a comparison for `π½` I strongly prefer to phrase it as `nβΈ<` or `nβΈβ€` so that smaller values go through the first one and larger functions go through the second. This doesn't apply so much when comparing two arguments since one is smaller but the other's larger, so I don't have an easy technique for that. +Here the selection function `π½` is `0βΈβ€`, while `π` is a list of two functions `β¨-β1, +β1β©`. On the first argument, `3`, `π½3` is `0β€3`, or `1`, so the function `+β1` from `π` is chosen. The use of array indices means "false" comes first in `π` and "true" comes second, which is backwards relative to if-else constructs in most programming languages (including BQN's own [predicates](block.md#predicates)). When using a comparison for `π½` I strongly prefer to phrase it as `nβΈ<` or `nβΈβ€` so that smaller values go through the first one and larger functions go through the second. This doesn't apply so much when comparing two arguments since one is smaller but the other's larger, so I don't have an easy answer for that. 2 >βΆβ£βΏβ’ 6 # A minimum function (β) The advantage of using an index is that Choose works with any number of options. - Fn β (β"rtd"ββ)βΆβ¨β½, 1βΈβ, 1βΈβ, β’β© # Reverse, take 1, drop 1 + Fn β (β"rtd"ββ)βΆβ¨β½, 1βΈβ, 1βΈβ, β’β© # Reverse, take 1, drop 1 Fn "r123" @@ -20,7 +20,7 @@ The advantage of using an index is that Choose works with any number of options. Fn "123" # Default -The selection function in `Fn` uses [Index of](search.md#index-of) (`β`) to find the index of the first character in the list `"rtd"`. An extra value in `π` serves as a default function if it's none of those, since the result of `π½` is `3` in that case. A similar function that's often useful is [Bins](order.md#bins), for grouping inputs into intervals rather than by exact matching. +The selection function in `Fn` uses [Index of](search.md#index-of) (`β`) to find the index of the first character in the list `"rtd"`. An extra value in `π` serves as a default function if it's none of those, since the result of `π½` is `3` in that case. A similar function that's often useful is [Bins](order.md#bins), for grouping inputs into intervals rather than by exact matching. Choose is necessary for [tacit](tacit.md) programming, but tacit programming is not necessary to be an effective BQN programmer! Consider using block features like [predicates](block.md#predicates) when Choose isn't working with your program's flow. diff --git a/doc/compose.md b/doc/compose.md index 9c8c2106..84c3987c 100644 --- a/doc/compose.md +++ b/doc/compose.md @@ -6,7 +6,7 @@ DrawComp β"ββ" --> -Atop and Over are 2-modifiers that extend the idea of "apply this, then that" in two different ways. They're modelled after the mathematical notation fβg to compose two functions, and both do the same thing when there's one argument: `FβG x` or `FβG x` is `F G x`. +Atop and Over are 2-modifiers that extend the idea of "apply this, then that" in two different ways. They're modelled after the mathematical notation fβg to compose two functions, and both do the same thing when there's one argument: either `FβG x` or `FβG x` is `F G x`. | `Cmp` | `Cmp π©` | `π¨ Cmp π©` | Unified | On list |-------|---------|:--------------:|:-----------:|:-------: @@ -17,7 +17,7 @@ When there are two arguments, we might say Atop treats the right operand `πΎ` ## Atop -Of the two modifiers on this page, Atop is more common but less impactful. The composition `FβG` is equivalent to the 2-[train](train.md) `F G` (the trains page has hints on when you'd choose one or the other). Its definition `{Fπ¨Gπ©}` means that `G` is applied to one or two arguments and `F` is applied monadically to the result. It could be considered a "default way" to compose two functions. Keeps [tacit](tacit.md) programming syntax running smoothly, without making noise about it. Not like that busybody `βΈ`. Some examples: +Of the two modifiers on this page, Atop is more common but less impactful. The composition `FβG` is equivalent to the 2-[train](train.md) `F G` (the trains page has hints on when you'd choose one or the other). Its definition `{Fπ¨Gπ©}` means that `G` is applied to one or two arguments and `F` is applied monadically to the result. It's sort of a "default way" to compose two functions. Keeps [tacit](tacit.md) programming syntax running smoothly, without making noise about it. Not like that busybody `βΈ`. Some examples: `βββ ` is useful with one argument: `ββ l` is a list of indices for `l`. @@ -35,7 +35,7 @@ Once you get used to Over, it's painful to go without it. I'd use it all the tim Usually Over is used just for the dyadic meaning. If you have a composition that only works with one argument it's typical to write it with Atop (`β`). And cases that work with one or two arguments do come up from time to time, but they're fairly rare, so the examples below are just for two arguments. -A classic is the function `β‘ββ§`, which tests whether `π¨` is a reordering of `π©`. The idea is to sort both arrays with `β§` to remove the ordering information +A classic is the function `β‘ββ§`, which tests whether `π¨` is a reordering of `π©`. The idea is to sort both arrays with `β§` to remove the ordering information, then see if they match. "BQN" β‘ββ§ "QNB" "BQN" β‘ββ§ "BBQ" diff --git a/docs/doc/arithmetic.html b/docs/doc/arithmetic.html index 46831cad..9e511044 100644 --- a/docs/doc/arithmetic.html +++ b/docs/doc/arithmetic.html @@ -22,6 +22,7 @@ <th>Symbol</th> <th>Dyad</th> <th>Monad</th> +<th align="center">default <code><span class='Value'>π¨</span></code></th> </tr> </thead> <tbody> @@ -29,35 +30,41 @@ <td><code><span class='Function'>+</span></code></td> <td>Add</td> <td><em>(Conjugate)</em></td> +<td align="center">β</td> </tr> <tr> <td><code><span class='Function'>-</span></code></td> <td>Subtract</td> <td>Negate</td> +<td align="center">0</td> </tr> <tr> <td><code><span class='Function'>Γ</span></code></td> <td>Multiply</td> <td>Sign</td> +<td align="center">β</td> </tr> <tr> <td><code><span class='Function'>Γ·</span></code></td> <td>Divide</td> <td>Reciprocal</td> +<td align="center">1</td> </tr> <tr> <td><code><span class='Function'>β</span></code></td> <td>Power</td> <td>Exponential</td> +<td align="center"><em>e</em></td> </tr> <tr> <td><code><span class='Function'>β</span></code></td> <td>Root</td> <td>Square root</td> +<td align="center">2</td> </tr> </tbody> </table> -<p>The dyadic functions should all be familiar operations, and most likely you are familiar with the symbols <code><span class='Function'>+-ΓΓ·β</span></code>. In fact the large <code><span class='Function'>Γ</span></code> and <code><span class='Function'>Γ·</span></code> might strike you as a regression to early school years, before division was written vertically and multiplication with a simple dot or no symbol at all (BQN reserves the distinction of having no symbol for application and composition). Like these, raising to a power or exponentiation is made regular by giving it the symbol <code><span class='Function'>β</span></code>βa true Unicode star and <em>not</em> an asterisk. The Root function <code><span class='Function'>β</span></code> is also modified to be a binary function, which raises <code><span class='Value'>π©</span></code> to the power <code><span class='Function'>Γ·</span><span class='Value'>π¨</span></code>. In ASCII programming languages <code><span class='Function'>Γ</span></code>, <code><span class='Function'>Γ·</span></code>, and <code><span class='Function'>β</span></code> are often written <code><span class='Value'>*</span></code>, <code><span class='Function'>/</span></code>, and <code><span class='Value'>^</span></code> or <code><span class='Value'>**</span></code>.</p> +<p>The dyadic (two-argument) functions should all be familiar operations, and most likely you know the symbols <code><span class='Function'>+-ΓΓ·β</span></code>. In fact the large <code><span class='Function'>Γ</span></code> and <code><span class='Function'>Γ·</span></code> might strike you as a regression to early school years, before division was written vertically and multiplication with a simple dot or no symbol at all. Like these, raising to a power or exponentiation is made regular by giving it the symbol <code><span class='Function'>β</span></code>βa true Unicode star and <em>not</em> an asterisk. The Root function <code><span class='Function'>β</span></code> is also modified to be a binary function, which raises <code><span class='Value'>π©</span></code> to the power <code><span class='Function'>Γ·</span><span class='Value'>π¨</span></code>. In ASCII programming languages <code><span class='Function'>Γ</span></code>, <code><span class='Function'>Γ·</span></code>, and <code><span class='Function'>β</span></code> are often written <code><span class='Value'>*</span></code>, <code><span class='Function'>/</span></code>, and <code><span class='Value'>^</span></code> or <code><span class='Value'>**</span></code>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MiArIDPigL8x4oC/MOKAvzUKCjLigL81IC0gMeKAvzkKCjEuNeKAvzLigL8wLjUgw5cgMgoKM+KAvzTigL8xIMO3IDIKCjMg4ouGIDDigL8x4oC/MgoKNCDiiJogODE=">βοΈ</a><pre> <span class='Number'>2</span> <span class='Function'>+</span> <span class='Number'>3</span><span class='Ligature'>βΏ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>5</span> β¨ 5 3 2 7 β© @@ -76,7 +83,7 @@ <span class='Number'>4</span> <span class='Function'>β</span> <span class='Number'>81</span> 3 </pre> -<p>Each of these functions also has a meaning with only one argument, although in mathematics only <code><span class='Function'>-</span></code> does. The relationship of negation to addition is extended to division (relative to multiplication) as well, so that <code><span class='Function'>Γ·</span><span class='Value'>π©</span></code> gives the reciprocal <code><span class='Number'>1</span><span class='Function'>Γ·</span><span class='Value'>π©</span></code> of its argument. Power (<code><span class='Function'>β</span></code>) is also extended with a default left argument of <a href="https://en.wikipedia.org/wiki/E_(mathematical_constant)">Euler's number</a> <em>e</em>. The default left argument for Root is 2, giving the well-known Square Root.</p> +<p>Each of these functions also has a meaning with only one argument, although mathematics only defines <code><span class='Function'>-</span></code> in this way. The relationship of negation to addition is extended to division (relative to multiplication) as well, so that <code><span class='Function'>Γ·</span><span class='Value'>π©</span></code> gives the reciprocal <code><span class='Number'>1</span><span class='Function'>Γ·</span><span class='Value'>π©</span></code> of its argument. Power (<code><span class='Function'>β</span></code>) is also extended with a default left argument of <a href="https://en.wikipedia.org/wiki/E_(mathematical_constant)">Euler's number</a> <em>e</em>. The default left argument for Root is 2, giving the well-known Square Root.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=LSA2CgrDtyAw4oC/MeKAvzIKCuKLhiAw4oC/MeKAvzIKCuKImiAw4oC/MeKAvzLigL80">βοΈ</a><pre> <span class='Function'>-</span> <span class='Number'>6</span> Β―6 @@ -90,7 +97,7 @@ β¨ 0 1 1.414213562373095 2 β© </pre> <p>Take note of the difference between the function <code><span class='Function'>-</span></code>, and the "high minus" character <code><span class='Number'>Β―</span></code>, which is a part of <a href="syntax.html#constants">numeric notation</a>. Also shown is the number <code><span class='Number'>β</span></code>, which BQN supports along with <code><span class='Number'>Β―β</span></code> (but depending on implementation BQN may or may not keep track of <code><span class='Number'>Β―0</span></code>. Integer optimization loses the distinction so it's best not to rely on it).</p> -<p>The logarithm is written with Undo: <code><span class='Function'>β</span><span class='Modifier'>βΌ</span></code>. As with Power, the default base is <em>e</em>, giving a natural logarithm.</p> +<p>The logarithm is written with <a href="undo.html">Undo</a>: <code><span class='Function'>β</span><span class='Modifier'>βΌ</span></code>. As with Power, the default base is <em>e</em>, giving a natural logarithm.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4ouG4oG8IDEwCgoyIOKLhuKBvCAxMDI0">βοΈ</a><pre> <span class='Function'>β</span><span class='Modifier'>βΌ</span> <span class='Number'>10</span> 2.302585092994046 @@ -186,7 +193,7 @@ <span class='Function'>|</span> <span class='Number'>Β―β</span><span class='Ligature'>βΏ</span><span class='Number'>Β―6</span><span class='Ligature'>βΏ</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>2</span> β¨ β 6 0 2 β© </pre> -<p>Floor (<code><span class='Function'>β</span></code>) returns the largest integer less than or equal to the argument, and Ceiling (<code><span class='Function'>β</span></code>) returns the smallest one greater than or equal to it. For this purpose <code><span class='Number'>Β―β</span></code> and <code><span class='Number'>β</span></code> are treated as integers, so that the floor or ceiling of an infinity is itself. Absolute value removes the argument's sign by negating it if it is less than 0, so that its result is always non-negative.</p> +<p>Floor (<code><span class='Function'>β</span></code>) returns the largest integer less than or equal to the argument, and Ceiling (<code><span class='Function'>β</span></code>) returns the smallest one greater than or equal to it. For this purpose <code><span class='Number'>Β―β</span></code> and <code><span class='Number'>β</span></code> are treated as integers, so that the floor or ceiling of an infinity is itself. Absolute value removes the sign of <code><span class='Value'>π©</span></code> by negating it if it's less than 0, so that its result is always non-negative.</p> <p>Minimum (<code><span class='Function'>β</span></code>) returns the smaller of its two arguments, and Maximum (<code><span class='Function'>β</span></code>) returns the larger. These functions are loosely related to Floor and Ceiling in their use of comparison, and can be defined similarly: for example, the minimum of two numbers is the largest number less than or equal to both of them. To take the minimum or maximum of an entire list, use a <a href="fold.html">fold</a>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MyDijIog4oaVOAoK4oy94oq44oyIIOKGlTg=">βοΈ</a><pre> <span class='Number'>3</span> <span class='Function'>β</span> <span class='Function'>β</span><span class='Number'>8</span> β¨ 0 1 2 3 3 3 3 3 β© @@ -194,7 +201,7 @@ <span class='Function'>β½</span><span class='Modifier2'>βΈ</span><span class='Function'>β</span> <span class='Function'>β</span><span class='Number'>8</span> β¨ 7 6 5 4 4 5 6 7 β© </pre> -<p>Modulus (<code><span class='Function'>|</span></code>) is similar to the modular division operation written <code><span class='Value'>%</span></code> in C-like languages, but it takes the arguments in the opposite order, and differs in its handling of negative arguments. It's defined to be <code><span class='Brace'>{</span><span class='Value'>π©</span><span class='Function'>-</span><span class='Value'>π¨</span><span class='Function'>Γβ</span><span class='Value'>π©</span><span class='Function'>Γ·</span><span class='Value'>π¨</span><span class='Brace'>}</span></code>, except that the multiplication should always return 0 if its right argument is 0, even if <code><span class='Value'>π¨</span></code> is infinite.</p> +<p>Modulus (<code><span class='Function'>|</span></code>) is similar to the modular division operation written <code><span class='Value'>%</span></code> in C-like languages, but it takes the arguments in the opposite order, and differs in its handling of negative arguments. It's the same computation as <code><span class='Brace'>{</span><span class='Value'>π©</span><span class='Function'>-</span><span class='Value'>π¨</span><span class='Function'>Γβ</span><span class='Value'>π©</span><span class='Function'>Γ·</span><span class='Value'>π¨</span><span class='Brace'>}</span></code> but probably has better precision.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MyB8IOKGlTgKCjMgfCDCrzU=">βοΈ</a><pre> <span class='Number'>3</span> <span class='Function'>|</span> <span class='Function'>β</span><span class='Number'>8</span> β¨ 0 1 2 0 1 2 0 1 β© @@ -291,11 +298,11 @@ β¨ β¨ 1 0 β© 1 1 β© β </pre> -<p>With two arguments many combinations are possible. Arrays of equal shape are matched element-wise, and an atom is matched to every element of an array.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MTDigL8yMOKAvzMwICsgNeKAvzbigL83CgoxMCDDlyA04oC/M+KAvzLiiY024oC/N+KAvzg=">βοΈ</a><pre> <span class='Number'>10</span><span class='Ligature'>βΏ</span><span class='Number'>20</span><span class='Ligature'>βΏ</span><span class='Number'>30</span> <span class='Function'>+</span> <span class='Number'>5</span><span class='Ligature'>βΏ</span><span class='Number'>6</span><span class='Ligature'>βΏ</span><span class='Number'>7</span> +<p>With two arguments, many combinations are possible. Arrays of equal shape are matched element-wise, and an atom is matched to every element of an array.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MTDigL8yMOKAvzMwICsgNeKAvzbigL83CgoxMCDDlyBbNOKAvzPigL8yLDbigL834oC/OF0=">βοΈ</a><pre> <span class='Number'>10</span><span class='Ligature'>βΏ</span><span class='Number'>20</span><span class='Ligature'>βΏ</span><span class='Number'>30</span> <span class='Function'>+</span> <span class='Number'>5</span><span class='Ligature'>βΏ</span><span class='Number'>6</span><span class='Ligature'>βΏ</span><span class='Number'>7</span> β¨ 15 26 37 β© - <span class='Number'>10</span> <span class='Function'>Γ</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='Function'>β</span><span class='Number'>6</span><span class='Ligature'>βΏ</span><span class='Number'>7</span><span class='Ligature'>βΏ</span><span class='Number'>8</span> + <span class='Number'>10</span> <span class='Function'>Γ</span> <span class='Bracket'>[</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='Separator'>,</span><span class='Number'>6</span><span class='Ligature'>βΏ</span><span class='Number'>7</span><span class='Ligature'>βΏ</span><span class='Number'>8</span><span class='Bracket'>]</span> ββ β΅ 40 30 20 60 70 80 diff --git a/docs/doc/array.html b/docs/doc/array.html index 827f05c0..f675b171 100644 --- a/docs/doc/array.html +++ b/docs/doc/array.html @@ -7,8 +7,8 @@ <h1 id="the-array"><a class="header" href="#the-array">The array</a></h1> <p>As BQN is an array language, it's often helpful to understand what an array is when writing BQN programs. Fully describing the concept is sometimes <a href="https://www.jsoftware.com/papers/array.htm">held to be tricky</a>; here we'll see definitions, examples, and metaphors.</p> <p>In BQN, as in APL, arrays are multidimensional, instead of strictly linear. Languages like Python, Javascript, or Haskell offer only one-dimensional arrays with <code><span class='Bracket'>[]</span></code> syntax, and typically represent multidimensional data with nested arrays. Multidimensional arrays have fundamental differences relative to this model.</p> -<p>BQN's arrays are immutable, meaning that an array is entirely defined by its attributes, and there is no way to modify an existing array, only to produce another array that has changes relative to it. As a result, an array can never contain itself, and arrays form an inductive type. BQN's <a href="lexical.html#mutation">mutable</a> types are operations and namespaces.</p> -<p>An array might also have a <a href="fill.html">fill element</a> that captures some structural information about its elements and is used by a few operations. The fill, as an inferred property, isn't considered to truly be part of the array but is instead some information about the array that the interpreter keeps track of. So it's out of scope here.</p> +<p>BQN's arrays are immutable, meaning that an array is entirely defined by its attributes, and there's no way to modify an existing array, only to produce another array that has changes relative to it. As a result, an array can never contain itself. BQN's <a href="lexical.html#mutation">mutable</a> types are operations and namespaces.</p> +<p>An array might also have a <a href="fill.html">fill element</a> that captures some structural information about its elements and is used by a few operations. As an inferred property, the fill isn't considered to truly be part of the array, but is instead some information about it that the interpreter keeps track of. So it's out of scope here.</p> <svg viewBox='-36 -15 544 426'> <g fill='currentColor' stroke-linecap='round' text-anchor='middle' font-size='14' font-family='BQN,monospace'> <rect class='code' stroke-width='1.5' rx='12' x='-4' y='0' width='480' height='396'/> @@ -106,7 +106,7 @@ <p>The axes of an array must be independent, that is, the positions present in one axis are fixed for the entire array and don't depend on other axes. This is a difference relative to a nested list model. When storing data in nested lists, the outer axis comes first and later axes are subordinate to it. The length of the second axis depends completely on the position in the first. A programmer might choose the lengths so it doesn't in a particular case, but in a BQN array differing lengths simply aren't representable.</p> <p>The array also needs to be complete. Every elementβevery combination of positionsβmust have a value. This value could be a placeholder like <code><span class='String'>@</span></code>, but it has to be <em>something</em> (in the spending example, everyone spends some amount at each store, even if it's zero). And of course, there are no extra elements that don't fit into the positioning systemβthe <a href="fill.html">fill</a> isn't really part of the array, but extra information about it.</p> <h2 id="ordering-and-indices"><a class="header" href="#ordering-and-indices">Ordering and indices</a></h2> -<p>To finish this definition of an array we also need to nail down the idea of a position. The positions along one dimension can't be labelled in any way, but they have a linear ordering (mathematically speaking, a <a href="https://en.wikipedia.org/wiki/Total_order">total order</a>: out of any two different positions one comes earlier and the other later). BQN keeps track of this order: for example, when we <a href="join.html">join</a> two arrays it places positions in <code><span class='Value'>π¨</span></code> before those of <code><span class='Value'>π©</span></code> and otherwise maintains the original ordering.</p> +<p>To finish this definition of an array we also need to nail down the idea of a position. The positions along one dimension can't have labels attached to them, but they have a linear ordering (mathematically speaking, a <a href="https://en.wikipedia.org/wiki/Total_order">total order</a>: out of any two different positions one comes earlier and the other later). BQN keeps track of this order: for example, when we <a href="join.html">join</a> two arrays it places positions in <code><span class='Value'>π¨</span></code> before those of <code><span class='Value'>π©</span></code> and otherwise maintains the original orderings.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImJlZm9yZSIg4oi+ICJhZnRlciI=">βοΈ</a><pre> <span class='String'>"before"</span> <span class='Function'>βΎ</span> <span class='String'>"after"</span> "beforeafter" </pre> @@ -116,10 +116,10 @@ <p>The number of axes in an array is called its <strong>rank</strong>. The number of positions along an axis is called its <strong>length</strong>, and the length of an array means its length along the first axis, or <code><span class='Number'>1</span></code> if there are no axes. The list of the lengths along each axis is the array's <strong>shape</strong>, and describes the possible element locations completely. In BQN they're exposed as the <a href="shape.html">functions</a> Rank (<code><span class='Function'>=</span></code>), Length (<code><span class='Function'>β </span></code>), and Shape (<code><span class='Function'>β’</span></code>).</p> <p>The total number of elements in an array is its <strong>bound</strong>, and can be found using <a href="reshape.html">Deshape</a> with <code><span class='Function'>β </span><span class='Modifier2'>β</span><span class='Function'>β₯</span></code>, or by multiplying all the lengths in the shape. An array of rank 0, which always contains exactly one element, is called a <a href="enclose.html#whats-a-unit"><strong>unit</strong></a>, while an array of rank 1 is called a <strong>list</strong> and an array of rank 2 is called a <strong>table</strong>.</p> <h2 id="elements"><a class="header" href="#elements">Elements</a></h2> -<p>Any BQN value can be used as an array element, including another array (BQN, as a dynamically-typed language, doesn't restrict the types that can be used in one context without a good reason). However, BQN arrays are restricted relative to other array models. Frameworks like NumPy or Julia have mutable arrays, so that the value of an element can be changed after the array is created. This allows an array to be its own element, by creating an array and then inserting it into itself. This would be unnatural in BQN, where an array can only be formed from elements that already exist. In BQN only operations and namespaces are <a href="lexical.html#mutation">mutable</a>.</p> -<p>An array with no elements (a bound of 0) is called <strong>empty</strong>. These arrays can cause problems when a property should be computed from the elements of an array, like the sum <code><span class='Function'>+</span><span class='Modifier'>Β΄</span><span class='Value'>π©</span></code> or shape of the <a href="couple.html#merge-and-array-theory">merged</a> array <code><span class='Function'>></span><span class='Value'>π©</span></code>. BQN has two mechanisms to make these cases work better. First, reductions like <code><span class='Function'>+</span><span class='Modifier'>Β΄</span></code> have <a href="fold.html#identity-values">identity values</a> for certain functions, so that <code><span class='Function'>+</span><span class='Modifier'>Β΄</span><span class='Bracket'>β¨β©</span></code> is <code><span class='Number'>0</span></code> for example. Second, every array might have a <a href="fill.html">fill element</a>, a special "typical element" for the array. Functions like Merge use this element's structure to determine the result shape when there are no actual elements to be used.</p> +<p>Any BQN value can be used as an array element, including another array (BQN, as a dynamically-typed language, doesn't restrict the types that can be used in one context without a good reason). However, BQN arrays are in some sense restricted relative to other array models. Frameworks like NumPy or Julia have mutable arrays, so that the value of an element can be changed after the array is created. This allows an array to be its own element, by creating an array and then inserting it into itself. This would be unnatural in BQN, where an array can only be formed from elements that already exist. In BQN only operations and namespaces are <a href="lexical.html#mutation">mutable</a>.</p> +<p>An array with no elements (a bound of 0) is called <strong>empty</strong>. These arrays can cause problems when a property should be computed from the elements of an array, like the sum <code><span class='Function'>+</span><span class='Modifier'>Β΄</span><span class='Value'>π©</span></code> or shape of the <a href="couple.html#merge-and-array-theory">merged</a> array <code><span class='Function'>></span><span class='Value'>π©</span></code>. BQN has two mechanisms to make these cases work better. First, Fold (<code><span class='Modifier'>Β΄</span></code>) and Insert (<code><span class='Modifier'>Λ</span></code>) have <a href="fold.html#identity-values">identity values</a> for certain functions, so that <code><span class='Function'>+</span><span class='Modifier'>Β΄</span><span class='Bracket'>β¨β©</span></code> is <code><span class='Number'>0</span></code> for example. Second, every array might have a <a href="fill.html">fill element</a>, a special "typical element" for the array. Functions like Merge use this element's structure to determine the result shape when there are no actual elements to be used.</p> <h2 id="cells"><a class="header" href="#cells">Cells</a></h2> -<p>The contents of an array are its elements, but it also makes sense to split up an array into subarrays of elements called cells. The most important kind of cell, a <strong>major cell</strong> consists of all the elements that have indices beginning with some particular index <code><span class='Value'>i</span></code>. For this to make sense, <code><span class='Value'>i</span></code> must be between <code><span class='Number'>0</span></code> and the length <code><span class='Value'>l</span></code> of the array's first axis, so that there are <code><span class='Value'>l</span></code> major cells each identified by an index.</p> +<p>The contents of an array are its elements, but it also makes sense to split up an array into subarrays of elements called cells. The most important kind of cell, a <strong>major cell</strong>, consists of all the elements whose indices begin with some particular index <code><span class='Value'>i</span></code>. For this to make sense, <code><span class='Value'>i</span></code> must be between <code><span class='Number'>0</span></code> and the length <code><span class='Value'>n</span></code> of the array's first axis, so that there are <code><span class='Value'>n</span></code> major cells each identified by an index.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MuKAvzPigL80IMOX4oycIDHigL814oC/OOKAvzExCgoxIOKKjyAy4oC/M+KAvzQgw5fijJwgMeKAvzXigL844oC/MTEgICMgTWFqb3IgY2VsbCAx">βοΈ</a><pre> <span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Number'>3</span><span class='Ligature'>βΏ</span><span class='Number'>4</span> <span class='Function'>Γ</span><span class='Modifier'>β</span> <span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Number'>5</span><span class='Ligature'>βΏ</span><span class='Number'>8</span><span class='Ligature'>βΏ</span><span class='Number'>11</span> ββ β΅ 2 10 16 22 @@ -130,12 +130,12 @@ <span class='Number'>1</span> <span class='Function'>β</span> <span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Number'>3</span><span class='Ligature'>βΏ</span><span class='Number'>4</span> <span class='Function'>Γ</span><span class='Modifier'>β</span> <span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Number'>5</span><span class='Ligature'>βΏ</span><span class='Number'>8</span><span class='Ligature'>βΏ</span><span class='Number'>11</span> <span class='Comment'># Major cell 1 </span>β¨ 3 15 24 33 β© </pre> -<p>A major cell still has an array structure: it retains all the axes of the original array other than the first. So it has its own major cells, identified by the index <code><span class='Value'>i</span></code> of the original major cell and <code><span class='Value'>j</span></code> within it. These are also cells of the original array. Generalizing, a <strong>cell</strong> with index list <code><span class='Value'>l</span></code> is defined to be the array of all elements whose indices begin with <code><span class='Value'>l</span></code>. In an array with rank <code><span class='Value'>n</span></code>, the cell rank is <code><span class='Value'>n</span><span class='Function'>-β </span><span class='Value'>l</span></code>, and cells grouped using this rank. An <code><span class='Value'>n</span></code>-cell mst have an empty cell index, so that it includes all elementsβit's the entire array! An <code><span class='Value'>n</span><span class='Function'>-</span><span class='Number'>1</span></code> cell, also called a Β―1-cell, is a major cell. A 0-cell has an index of length <code><span class='Value'>n</span></code>, and contains a single element.</p> +<p>A major cell still has an array structure: it retains all the axes of the original array other than the first. So it has its own major cells, identified by the index <code><span class='Value'>i</span></code> of the original major cell and <code><span class='Value'>j</span></code> within it. These are also cells of the original array. Generalizing, a <strong>cell</strong> with index list <code><span class='Value'>l</span></code> is defined to be the array of all elements whose indices begin with <code><span class='Value'>l</span></code>. In an array with rank <code><span class='Value'>r</span></code>, the cell rank is <code><span class='Value'>r</span><span class='Function'>-β </span><span class='Value'>l</span></code>, and cells grouped using this rank. An <code><span class='Value'>r</span></code>-cell must have an empty cell index, so that it includes all elementsβit's the entire array! An <code><span class='Value'>r</span><span class='Function'>-</span><span class='Number'>1</span></code> cell, also called a Β―1-cell, is a major cell. A 0-cell has an index of length <code><span class='Value'>r</span></code>, and contains a single element.</p> <p>Cells are the center of the <a href="leading.html">leading axis model</a> used to structure many array primitives.</p> <h2 id="properties"><a class="header" href="#properties">Properties</a></h2> <p>Summarizing, the values needed to define an array are its rank (the number of axes), its shape (the number of positions along each axis), and the value of each element (that is, at each combination of positions). Two arrays <a href="match.html">match</a> when all these values match.</p> -<p>If the rank is considered to be part of the shape, as it is when the shape is a BQN list, then the array is defined by its shape and element listβfrom <a href="reshape.html">deshape</a>.</p> -<p>Here's a somewhat informal mathematical take. Given a set of possible element values <code><span class='Function'>T</span></code>, a <em>list</em> of <code><span class='Function'>T</span></code> of length <code><span class='Value'>l</span></code> is a map from natural numbers less than <code><span class='Value'>l</span></code> to <code><span class='Function'>T</span></code>. An array is a rank <code><span class='Value'>r</span></code>, along with a list <code><span class='Value'>s</span></code> of natural numbers of length <code><span class='Value'>r</span></code>, and a map from lists of natural numbers <code><span class='Value'>i</span></code> that satisfy <code><span class='Value'>i</span><span class='Paren'>(</span><span class='Value'>j</span><span class='Paren'>)</span> <span class='Function'><</span> <span class='Value'>s</span><span class='Paren'>(</span><span class='Value'>j</span><span class='Paren'>)</span></code> for all natural numbers <code><span class='Value'>j</span><span class='Function'><</span><span class='Value'>r</span></code> to BQN values. Arrays are an inductive type, so that an array can only be defined using elements that already exist. As a result an array's elements are always values of lesser complexity and selecting one element of an array, then an element of that element, and so on, must eventually reach a non-array.</p> +<p>If the rank is considered to be part of the shape, as it is when the shape is a BQN list, then the array is defined by its shape, and element list as returned by <a href="reshape.html">deshape</a>.</p> +<p>Here's a somewhat informal mathematical take. Given a set of possible element values <code><span class='Function'>T</span></code>, a <em>list</em> of <code><span class='Function'>T</span></code> of length <code><span class='Value'>l</span></code> is a map from natural numbers less than <code><span class='Value'>l</span></code> to <code><span class='Function'>T</span></code>. An array is a rank <code><span class='Value'>r</span></code>, along with a list <code><span class='Value'>s</span></code> of natural numbers of length <code><span class='Value'>r</span></code>, and a map from lists of natural numbers <code><span class='Value'>i</span></code> that satisfy <code><span class='Value'>i</span><span class='Paren'>(</span><span class='Value'>j</span><span class='Paren'>)</span> <span class='Function'><</span> <span class='Value'>s</span><span class='Paren'>(</span><span class='Value'>j</span><span class='Paren'>)</span></code> for all natural numbers <code><span class='Value'>j</span><span class='Function'><</span><span class='Value'>r</span></code> to BQN values. Arrays are an inductive type, so that an array can only be defined using elements that already exist. As a result, an array's elements are always values of lesser complexity than it: selecting one element of an array, then an element of that element, and so on, must eventually reach a non-array.</p> <h2 id="why-arrays"><a class="header" href="#why-arrays">Why arrays?</a></h2> <p>The multidimensional array is a fairly simple structure, but there are simpler ones like pairs, lists, sets, and dictionaries. Why does BQN choose the array for its central type? I don't think arrays are always the best data structure (or that BQN is always the best language), but I do think they're one of several good choices and have unique advantages.</p> <p>Arrays offer a lot of flexibility since they generalize lists. This also means that they can be used to represent pairs or sets. Two lists, or an array with a length-2 axis, can represent a map, although it could be hard to use with good performance.</p> diff --git a/docs/doc/arrayrepr.html b/docs/doc/arrayrepr.html index 06a55f82..159bb8f7 100644 --- a/docs/doc/arrayrepr.html +++ b/docs/doc/arrayrepr.html @@ -5,10 +5,10 @@ </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div> <h1 id="array-notation-and-display"><a class="header" href="#array-notation-and-display">Array notation and display</a></h1> -<p>This page documents ways arrays are represented in BQN: the notation you can use to write them and the way the REPL displays them.</p> +<p>This page documents ways <a href="array.html">arrays</a> are represented in BQN: the notation you can use to write them and the way the REPL displays them.</p> <p>Array display is a feature of a BQN environment such as a REPL. You can also access it with <code><span class='Function'>β’Fmt</span></code>, which takes a value and returns a string indicating how it would be formatted. Array notation is of course part of BQN source code, but you can also go from an array to one possible source code for it using the similar system function <code><span class='Function'>β’Repr</span></code>.</p> <h2 id="array-display"><a class="header" href="#array-display">Array display</a></h2> -<p>Although it's really part of the language environment and not BQN itself, let's look at display first so it's clear what arrays we're talking about later on. The BQN REPL prints arrays in a way that's meant to unambiguously show the structure and data, but doesn't correspond to BQN source code. A few examples are given below; of course, displays like this appear all over the documentation.</p> +<p>Although it's really part of the language environment and not BQN itself, let's look at display first so it's clear what arrays we're talking about later on. A BQN session prints arrays in a way that's meant to unambiguously show the structure and data, but doesn't correspond to BQN source code. A few examples are given below; of course, displays like this appear all over the documentation.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oaVIDPigL80ICAgICAgICAgICAgICMgQXJyYXkgb2YgbGlzdHMKCjxAICAgICAgICAgICAgICAgICMgRW5jbG9zZWQgbnVsbAoK4p+o4oaVMywgInh5Iiwg4oaVMuKAvzDin6kgICMgQSBsaXN0IG9mIHRocmVlIGFycmF5cw==">βοΈ</a><pre> <span class='Function'>β</span> <span class='Number'>3</span><span class='Ligature'>βΏ</span><span class='Number'>4</span> <span class='Comment'># Array of lists </span>ββ β΅ β¨ 0 0 β© β¨ 0 1 β© β¨ 0 2 β© β¨ 0 3 β© @@ -42,7 +42,7 @@ β β </pre> -<p>The lack of extra separation is to make it clear that the corners enclose the array rather than any of its elements (elements are still distinguishable becase an individual element won't contain whitespace except maybe between quotes). Now every set of corners indicates one array. This is a good fit for the <a href="based.html">based array model</a>, where data doesn't have to be in an array.</p> +<p>The lack of extra separation is to make it clear that the corners enclose the whole array rather than any of its elements (elements are still distinguishable becase an individual element won't contain whitespace, except maybe between quotes). Every set of corners indicates one array. This is a good fit for the <a href="based.html">based array model</a>, where data doesn't have to be in an array.</p> <h4 id="rank-indicator"><a class="header" href="#rank-indicator">Rank indicator</a></h4> <p>The top left corner indicates the rank of an array. Here's a neat way using <a href="fold.html">Fold</a> (<code><span class='Modifier'>Β΄</span></code>) and <a href="prefixes.html">Prefixes</a> (<code><span class='Function'>β</span></code>) to nest ranks 0 through 6 together:</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MCDipYrin5w8wrQg4oaRNuKlijE=">βοΈ</a><pre> <span class='Number'>0</span> <span class='Function'>β₯</span><span class='Modifier2'>β</span><span class='Function'><</span><span class='Modifier'>Β΄</span> <span class='Function'>β</span><span class='Number'>6</span><span class='Function'>β₯</span><span class='Number'>1</span> @@ -121,7 +121,7 @@ β </pre> <h4 id="empty-arrays"><a class="header" href="#empty-arrays">Empty arrays</a></h4> -<p>The top-left corner can show the rank of an array but not its shape; the shape must be seen from the data. An empty array has no data, and it's hard to tell shape from a bunch of blank space. In general, an empty array is printed as <code><span class='Function'>β</span><span class='Value'>shape</span></code>. An empty list is shown using brackets <code><span class='Bracket'>β¨β©</span></code>, which are discussed in the next section.</p> +<p>The top-left corner can show the rank of an array but not its shape; the shape must be seen from the data. An empty array has no data, and it can be impossible to tell shape from a bunch of blank space. So an empty array is usually printed as <code><span class='Function'>β</span><span class='Value'>shape</span></code>. An empty list is shown using brackets <code><span class='Bracket'>β¨β©</span></code>, which are discussed in the next section.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oaVwqgg4p+oMOKAvzQsIDPigL8w4oC/MSwgMuKAvzDigL8wLCAw4p+p">βοΈ</a><pre> <span class='Function'>β</span><span class='Modifier'>Β¨</span> <span class='Bracket'>β¨</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>4</span><span class='Separator'>,</span> <span class='Number'>3</span><span class='Ligature'>βΏ</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>1</span><span class='Separator'>,</span> <span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>0</span><span class='Separator'>,</span> <span class='Number'>0</span><span class='Bracket'>β©</span> β¨ β0βΏ4 β3βΏ0βΏ1 β2βΏ0βΏ0 β¨β© β© </pre> @@ -157,10 +157,10 @@ <span class='String'>""</span> β¨β© </pre> -<p>This case also covers empty lists, which are shown as <code><span class='Bracket'>β¨β©</span></code>. This includes an empty string, as the only difference between an empty string and any other empty list is its fill element and array displays don't depend on the fill.</p> +<p>This case also covers empty lists, which are shown as <code><span class='Bracket'>β¨β©</span></code>. This includes an empty string: the only difference between an empty string and any other empty list is its fill element, and array displays don't depend on the fill.</p> <h2 id="array-literals"><a class="header" href="#array-literals">Array literals</a></h2> <p><em>The tutorial section <a href="../tutorial/list.html#list-notation">here</a> also covers this topic.</em></p> -<p>There are three kinds literal notation for lists: strings, list notation, and stranding. Strings indicate character lists (with space for the <a href="fill.html">fill</a>) and the other two can combine any sequence of elements. Additionally, there's a square bracket notation that can form higher-rank arrays.</p> +<p>Now it's time to discuss ways to write arrays in a BQN program. There are three kinds literal notation for lists: strings, list notation, and stranding. Strings indicate character lists (with space for the <a href="fill.html">fill</a>) and the other two can combine any sequence of elements. Additionally, there's a square bracket notation that can form higher-rank arrays.</p> <h3 id="strings"><a class="header" href="#strings">Strings</a></h3> <p>A <strong>string</strong> consists of a sequence of characters surrounded by double quotes <code><span class='String'>""</span></code>. The only rule for the characters inside is that any double quote must be escaped by repeating it twice; otherwise the string ends at that point.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Ii0nw5clIiIqIgoKIi0nw5clIioiICAjIEVzY2FwaW5nIGZhaWx1cmU=">βοΈ</a><pre> <span class='String'>"-'Γ%""*"</span> @@ -172,7 +172,7 @@ <p>Even special characters like a newline can appear in a string literal, so that string literals are automatically multi-line.</p> <h3 id="brackets"><a class="header" href="#brackets">Brackets</a></h3> <p><strong>List notation</strong> uses angle brackets <code><span class='Bracket'>β¨β©</span></code>. The contents are structurally identical to those of a <a href="block.html">block</a>, that is, a list of expressions <a href="syntax.html#separators">separated</a> by <code><span class='Separator'>,</span></code> or <code><span class='Separator'>β</span></code> or newlines. Unlike a block, a list doesn't need to have any expressions: <code><span class='Bracket'>β¨β©</span></code> or <code><span class='Bracket'>β¨</span><span class='Separator'>β</span><span class='Bracket'>β©</span></code> or <code><span class='Bracket'>β¨</span><span class='Separator'>,,β,</span><span class='Bracket'>β©</span></code> will create an empty list. Other differences are that a list doesn't introduce a new <a href="lexical.html">scope</a> and all of the expressions have to result in a value, not <a href="expression.html#nothing">Nothing</a> (<code><span class='Nothing'>Β·</span></code>).</p> -<p>Entries in a list are evaluated in source order, and the value will be the list of those results. The list has a subject role, even if it contains expressions with other roles. Any value can be an element.</p> +<p>Entries in a list are evaluated in source order, and the value will be the list of those results. The list has a subject <a href="expression.html#syntactic-role">role</a>, even if it contains expressions with other roles. Any value can be an element.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4p+oQCwg4o2Jy5gsIOKJjSJhYmMi4p+p">βοΈ</a><pre> <span class='Bracket'>β¨</span><span class='String'>@</span><span class='Separator'>,</span> <span class='Function'>β</span><span class='Modifier'>Λ</span><span class='Separator'>,</span> <span class='Function'>β</span><span class='String'>"abc"</span><span class='Bracket'>β©</span> ββ Β· @ βΛ ββ @@ -180,7 +180,7 @@ β β </pre> -<p>BQN's separator rules give list notation a very flexible structure. You can put all the elements on one line or spread them across lines, with the option of adding blank lines between elements. A separator at the end of a line is never needed but leading and trailing separators are allowed.</p> +<p>BQN's separator rules give list notation a very flexible structure. You can put all the elements on one line or spread them across lines, with the option of adding blank lines between elements. A separator at the end of a line is never needed, but leading and trailing separators are allowed.</p> <pre><span class='Bracket'>β¨</span> <span class='String'>"e0"</span><span class='Separator'>,</span> <span class='String'>"e1"</span> <span class='Bracket'>β¨</span> @@ -201,9 +201,9 @@ 0 5 β </pre> -<p>This syntax doesn't work for creating rank 0 arraysβuse <a href="enclose.html">Enclose</a> <code><span class='Function'><</span></code> for theseβor empty arrays. The notation <code><span class='Bracket'>[]</span></code> would be ambiguous, so it's not allowed (although it can be used for destructuring, which works with an existing array). To create a specific empty array, <a href="reshape.html">Reshape</a> (<code><span class='Function'>β₯</span></code>) is probably the best approach.</p> +<p>This syntax doesn't work for creating rank 0 arraysβuse <a href="enclose.html">Enclose</a> <code><span class='Function'><</span></code> for theseβor empty arrays. The notation <code><span class='Bracket'>[]</span></code> would be ambiguous, so it's not allowed (although it can be used for destructuring, which works with an existing array). To create an empty array with a specific shape, <a href="reshape.html">Reshape</a> (<code><span class='Function'>β₯</span></code>) is probably the best approach.</p> <h3 id="strands"><a class="header" href="#strands">Strands</a></h3> -<p><strong>Strand notation</strong> is another way to write lists of length two or more. The elements are connected with the ligature character <code><span class='Ligature'>βΏ</span></code>. It has a precedence lower than the <a href="namespace.html">namespace</a> dot but higher than anything else other than paired brackets <code><span class='Paren'>()</span></code>, <code><span class='Brace'>{}</span></code>, and <code><span class='Bracket'>β¨β©</span></code>, so compound elements generally need to be placed in parentheses. Expressions joined by ligatures behave exactly the same as those in list notation: they are evaluated in order and placed in a list.</p> +<p><strong>Strand notation</strong> is another way to write lists of length two or more. The elements are connected with the ligature character <code><span class='Ligature'>βΏ</span></code>. It has a precedence higher than anything else other than the <a href="namespace.html">namespace</a> dot <code><span class='Value'>.</span></code> and of course paired brackets <code><span class='Paren'>()</span></code>, <code><span class='Brace'>{}</span></code>, and <code><span class='Bracket'>β¨β©</span></code>. This means complicated elements generally need to be placed in parentheses. Expressions joined by ligatures behave exactly the same as those in list notation: they are evaluated in order and placed in a list.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=K+KAv8K04oC/4oiY4oC/w5cKCivigL/CtOKAv+KImOKAv8OXICDiiaEgIOKfqCsswrQs4oiYLMOX4p+p">βοΈ</a><pre> <span class='Function'>+</span><span class='Ligature'>βΏ</span><span class='Modifier'>Β΄</span><span class='Ligature'>βΏ</span><span class='Modifier2'>β</span><span class='Ligature'>βΏ</span><span class='Function'>Γ</span> β¨ + Β΄ β Γ β© diff --git a/docs/doc/assert.html b/docs/doc/assert.html index ceccf72a..d800155f 100644 --- a/docs/doc/assert.html +++ b/docs/doc/assert.html @@ -8,28 +8,35 @@ <p>BQN provides some simple facilities for dealing with errors. Errors are an unusual sort of control flow; if possible, prefer to work with functions that return normally.</p> <h2 id="assert"><a class="header" href="#assert">Assert</a></h2> <p>BQN takes the position that errors exist to indicate exceptional conditions that the developer of a given program didn't expect. However, the types of errors that BQN naturally checks for, such as mismatched shapes in Couple (<code><span class='Function'>β</span></code>), aren't always enough to detect exceptional conditions. Issues like numeric values that don't make physical sense will slip right through. BQN makes it easy for a programmer to check for these sorts of problems by building in the primitive Assert, written <code><span class='Function'>!</span></code>. This function checks whether <code><span class='Value'>π©</span></code> matches <code><span class='Number'>1</span></code>: if it does, then it does nothing and returns <code><span class='Value'>π©</span></code>, and otherwise it gives an error.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAyPTIgICMgUGFzc2VkCiEgMj0zICAjIEZhaWxlZA==">βοΈ</a><pre> <span class='Function'>!</span> <span class='Number'>2</span><span class='Function'>=</span><span class='Number'>2</span> <span class='Comment'># Passed +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAyPTIgICMgUGFzc2VkCgohIDI9MyAgIyBGYWlsZWQ=">βοΈ</a><pre> <span class='Function'>!</span> <span class='Number'>2</span><span class='Function'>=</span><span class='Number'>2</span> <span class='Comment'># Passed </span>1 + <span class='Function'>!</span> <span class='Number'>2</span><span class='Function'>=</span><span class='Number'>3</span> <span class='Comment'># Failed </span><span class='Error'>Error: Assertion error</span> </pre> <p>To pass, the right argument must be exactly the number <code><span class='Number'>1</span></code>; any other value causes an error. For example, an array of <code><span class='Number'>1</span></code>s still causes an error; use <code><span class='Function'>β§</span><span class='Modifier'>Β΄</span><span class='Function'>β₯</span></code> to convert a boolean array to a single boolean that indicates whether all of its values are true.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAo4oinPeKIqOKMvsKsKeKMnMucIOKGlTIKISDiiKfCtOKliiAo4oinPeKIqOKMvsKsKeKMnMucIOKGlTI=">βοΈ</a><pre> <span class='Function'>!</span> <span class='Paren'>(</span><span class='Function'>β§=β¨</span><span class='Modifier2'>βΎ</span><span class='Function'>Β¬</span><span class='Paren'>)</span><span class='Modifier'>βΛ</span> <span class='Function'>β</span><span class='Number'>2</span> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAo4oinPeKIqOKMvsKsKeKMnMucIOKGlTIKCiEg4oinwrTipYogKOKIpz3iiKjijL7CrCnijJzLnCDihpUy">βοΈ</a><pre> <span class='Function'>!</span> <span class='Paren'>(</span><span class='Function'>β§=β¨</span><span class='Modifier2'>βΎ</span><span class='Function'>Β¬</span><span class='Paren'>)</span><span class='Modifier'>βΛ</span> <span class='Function'>β</span><span class='Number'>2</span> <span class='Error'>Error: 2βΏ2β₯1βΏ1βΏ1βΏ1</span> + <span class='Function'>!</span> <span class='Function'>β§</span><span class='Modifier'>Β΄</span><span class='Function'>β₯</span> <span class='Paren'>(</span><span class='Function'>β§=β¨</span><span class='Modifier2'>βΎ</span><span class='Function'>Β¬</span><span class='Paren'>)</span><span class='Modifier'>βΛ</span> <span class='Function'>β</span><span class='Number'>2</span> 1 </pre> -<p>Assert can take a left argument, which gives a message to be associated with the error. It's typical to use a string for the left argument in order to display it to the programmer, but the left argument can be any value.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Ik1lc3NhZ2UiICEgMArin6jiiJgsImFiYyIsy5zin6kgISAnMCc=">βοΈ</a><pre> <span class='String'>"Message"</span> <span class='Function'>!</span> <span class='Number'>0</span> +<p>Assert can take a left argument, which gives a message to be associated with the error. It's typical to use a string for <code><span class='Value'>π¨</span></code> in order to display it to the programmer, but <code><span class='Value'>π¨</span></code> can be any value.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Ik1lc3NhZ2UiICEgMAoK4p+o4oiYLCJhYmMiLMuc4p+pICEgJzAn">βοΈ</a><pre> <span class='String'>"Message"</span> <span class='Function'>!</span> <span class='Number'>0</span> <span class='Error'>Error: Message</span> + <span class='Bracket'>β¨</span><span class='Modifier2'>β</span><span class='Separator'>,</span><span class='String'>"abc"</span><span class='Separator'>,</span><span class='Modifier'>Λ</span><span class='Bracket'>β©</span> <span class='Function'>!</span> <span class='String'>'0'</span> <span class='Error'>Error: β¨β,"abc",Λβ©</span> </pre> +<p>In the 1-argument case, <code><span class='Value'>π©</span></code> is used for the error message if it's not <code><span class='Number'>1</span></code>. So an unconditional error can also be written this way:</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAiTWVzc2FnZSI=">βοΈ</a><pre> <span class='Function'>!</span> <span class='String'>"Message"</span> +<span class='Error'>Error: Message</span> +</pre> <h3 id="computing-the-error-message-on-demand"><a class="header" href="#computing-the-error-message-on-demand">Computing the error message on demand</a></h3> <p>Because the left argument to a function is always computed before the function is called, Assert <a href="../commentary/problems.html#assert-has-no-way-to-compute-the-error-message">doesn't let you</a> compute the error message only if there's an error. This might be a problem if the error message computation is slow or has side effects. There are a few ways to work around the issue:</p> <ul> -<li>Handle errors with ordinary if-then logic (perhaps using <a href="control.html">control structures</a>). This is probably the best path for user-facing applications where displaying an error goes through the user interface.</li> -<li>Write a function <code><span class='Function'>Message</span></code> to compute the message, and call <code><span class='Value'>π¨</span> <span class='Function'>Message</span><span class='Modifier2'>βΈ</span><span class='Function'>!</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'>π©</span></code> or similar instead of <code><span class='Function'>!</span></code>.</li> +<li>Handle bad inputs with ordinary if-then logic (perhaps using <a href="control.html">control structures</a>), not errors. This is probably the best path for user-facing applications where BQN's normal error display isn't wanted.</li> +<li>Write a function <code><span class='Function'>Message</span></code> to compute the message, and call <code><span class='Function'>!</span><span class='Modifier2'>β</span><span class='Function'>Message</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'>π©</span></code> or similar instead of <code><span class='Function'>!</span></code>.</li> <li>If the error will be caught elsewhere in the program, use a closure for the message and evaluate it when caught. With a function <code><span class='Function'>Message</span></code> as above, <code><span class='Value'>message</span> <span class='Function'>!</span> <span class='Value'>π©</span></code> works, and <code><span class='Brace'>{</span><span class='Value'>β¦</span><span class='Brace'>}</span><span class='Modifier'>Λ</span><span class='Modifier2'>βΈ</span><span class='Function'>!</span> <span class='Value'>π©</span></code> is a convenient syntax for block functions.</li> </ul> <h2 id="catch"><a class="header" href="#catch">Catch</a></h2> diff --git a/docs/doc/based.html b/docs/doc/based.html index f03adf29..4aa345f9 100644 --- a/docs/doc/based.html +++ b/docs/doc/based.html @@ -11,7 +11,7 @@ <p>If you're an array programmer then I have bad news for you. My thesis here is that APL took a wrong turn around 1981 when it extrapolated the excellent, but limited, flat array model of APL\360 to the ill-founded nested array model and the rigorous but clumsy boxed array model. Make that two wrong turns, I guess. Simultaneously. Anyway, if you've been brought up in either of these array models, then the best thing to do when starting BQN is to throw out your existing ideas about array depth and nesting (but don't worry too much: the fundamental concept of an array as a rectangular collection of data still holds!). If you'd like to ponder the relationship of BQN to APL later, that's great, but trying to initially understand BQN in terms of APL or J will just cause confusion.</p> <h2 id="starting-from-atoms"><a class="header" href="#starting-from-atoms">Starting from atoms</a></h2> <p>APL tends to define its data by starting with the array and then looking downwards in depth at what it contains. The based array model, as the name suggests, starts at the foundations, which in BQN are called "atoms". There are six <a href="types.html">types</a> of atom, which together with the array type give the seven types a value can have in BQN. Based means being yourself, and an atom's <em>not</em> an array.</p> -<p>An atom has <a href="depth.html">depth</a> 0, and doesn't inherently have a shape. However, primitives that expect an array promote atoms by <a href="enclose.html">enclosing</a> them to get a rank-0, or <em>unit</em>, array that contains the atom (any value can be enclosed in this way, giving a unit array with higher depth, but it only happens automatically for atoms). <a href="shape.html">Rank and shape</a> both do this, so an atom can be considered to have the same dimensions as a unit array: rank 0 and shape <code><span class='Bracket'>β¨β©</span></code>. An atom is also considered a kind of unit, but it's not a unit array.</p> +<p>An atom has <a href="depth.html">depth</a> 0, and doesn't inherently have a shape. However, primitives that expect an array will promote an atom by <a href="enclose.html">enclosing</a> to get a rank-0, or <em>unit</em>, array that contains it (any value can be enclosed in this way, giving a unit array with higher depth, but it only happens automatically for atoms). <a href="shape.html">Rank and shape</a> both do this, so an atom can be considered to have the same dimensions as a unit array: rank 0 and shape <code><span class='Bracket'>β¨β©</span></code>. An atom is also considered a kind of unit, but it's not a unit array.</p> <p>Atoms are displayed as plain values, while enclosed atoms, that is, depth-1 unit arrays, are shown with an array display.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MyAgICAjIEF0b20KPDMgICAjIEFycmF5CiczJyAgIyBBdG9t">βοΈ</a><pre> <span class='Number'>3</span> <span class='Comment'># Atom </span>3 diff --git a/docs/doc/birds.html b/docs/doc/birds.html index 09f70f84..18a1389a 100644 --- a/docs/doc/birds.html +++ b/docs/doc/birds.html @@ -5,7 +5,7 @@ </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div> <h1 id="bqn-for-birdwatchers"><a class="header" href="#bqn-for-birdwatchers">BQN for birdwatchers</a></h1> -<p>Some people consider it reasonable to name <a href="primitive.html#modifiers">combinators</a> after types of birds. <a href="https://blog.lahteenmaki.net/combinator-birds.html">Here's</a> one compendium of such names, and <a href="https://wiki.xxiivv.com/site/ornithodex.html">another</a> that lacks its obsessive completeness but makes up for it with rambling accounts of imagined forests. There is something wrong with these people. Some of these birds are not even real. "Quixotic bird"? Have you not heard of a quail? Nonetheless, I don't judge such afflicted souls (certainly not publicly), and have provided this translation table to explain BQN in terms they can understand.</p> +<p>Some people consider it reasonable to name <a href="primitive.html#modifiers">combinators</a> after types of birds. <a href="https://blog.lahteenmaki.net/combinator-birds.html">Here's</a> one compendium of such names, and <a href="https://wiki.xxiivv.com/site/ornithodex.html">another</a> that lacks its obsessive completeness but makes up for it with <a href="https://wiki.xxiivv.com/site/logic.html">rambling accounts</a> of imagined forests. There is something wrong with these people. Some of these birds are not even real. "Quixotic bird"? Have you not heard of a quail? Nonetheless, I don't judge such afflicted souls (certainly not publicly), and have provided this translation table to explain BQN in terms they can understand.</p> <table> <thead> <tr> diff --git a/docs/doc/block.html b/docs/doc/block.html index 31f59aed..a79791df 100644 --- a/docs/doc/block.html +++ b/docs/doc/block.html @@ -5,14 +5,15 @@ </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div> <h1 id="blocks"><a class="header" href="#blocks">Blocks</a></h1> -<p>In BQN, a <em>block</em> is any piece of code surrounded with curly braces <code><span class='Brace'>{}</span></code>. Blocks can be used simply to group statements, or can define functions or modifiers. They are the sole large-scale structure used to organize programs. An important aspect of organization is <a href="namespace.html">namespaces</a>, which are created with blocks but not discussed on this page.</p> +<p>In BQN, a <em>block</em> is any piece of code surrounded with curly braces <code><span class='Brace'>{}</span></code>. Blocks can be used simply to group statements, or can define functions or modifiers. They are the sole large-scale structure used to organize programs. One organizing tool not discussed here is <a href="namespace.html">namespaces</a>, which are created with blocks but have their own page. Programming without blocks (only recommended at the small scale) is called <a href="tacit.html">tacit</a> programming.</p> <p>Blocks are most commonly used to define functions by including one of the special names for arguments, <code><span class='Value'>π¨</span></code> or <code><span class='Value'>π©</span></code>. With the operands <code><span class='Function'>π½</span></code> or <code><span class='Function'>πΎ</span></code>, they can also define 1-modifiers or 2-modifiers.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=e/CdlakrMX0gMwrDl3vwnZWp8J2UvfCdlal9IDQ=">βοΈ</a><pre> <span class='Brace'>{</span><span class='Value'>π©</span><span class='Function'>+</span><span class='Number'>1</span><span class='Brace'>}</span> <span class='Number'>3</span> 4 <span class='Function'>Γ</span><span class='Brace'>{</span><span class='Value'>π©</span><span class='Function'>π½</span><span class='Value'>π©</span><span class='Brace'>}</span> <span class='Number'>4</span> 16 </pre> -<p>Because they use <a href="lexical.html">lexical scoping</a>, blocks can also be used to encapsulate code. If a block uses only variables that it initializes, then it has no dependence on its environment and would work the same way if defined anywhere. But it can also use external variables, defined in a containing block.</p> +<p>A block <a href="#block-headers">header</a> is written before a <code><span class='Head'>:</span></code> and describes the block type, and what inputs it accepts. A block can be split into <a href="#multiple-bodies">multiple bodies</a> using <code><span class='Head'>;</span></code>s, so that each handles different cases. A <a href="#predicates">predicate</a>, written with <code><span class='Head'>?</span></code>, can test an arbitrary condition to refine these cases.</p> +<p>Because they use <a href="lexical.html">lexical scoping</a>, blocks also encapsulate code. If a block uses only variables that it initializes, then it has no dependence on its environment and would work the same way if defined anywhere. But it can also use external variables, defined in a containing block.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=YeKGkGLihpAib3V0ZXIiCnsgYeKGkCJpbm5lciIg4ouEIGHigL9iIH0=">βοΈ</a><pre> <span class='Value'>a</span><span class='Gets'>β</span><span class='Value'>b</span><span class='Gets'>β</span><span class='String'>"outer"</span> <span class='Brace'>{</span> <span class='Value'>a</span><span class='Gets'>β</span><span class='String'>"inner"</span> <span class='Separator'>β</span> <span class='Value'>a</span><span class='Ligature'>βΏ</span><span class='Value'>b</span> <span class='Brace'>}</span> β¨ "inner" "outer" β© @@ -23,7 +24,7 @@ <span class='Value'>updown</span> β¨ 0 1 2 3 4 4 3 2 1 0 β© </pre> -<p>An immediate block is only ever evaluated once, and can't be used for control flow in a program. Including special names in a headerless block lets us define functions and modifiers, which have a broader range of uses. All special names are listed below:</p> +<p>An immediate block is only ever evaluated once, and can't be used for control flow in a program. Special names can be used to define <a href="ops.html">functions and modifiers</a>, which have a broader range of uses. All special names are listed below:</p> <table> <thead> <tr> @@ -65,14 +66,16 @@ </tr> </tbody> </table> -<p>Of these, <code><span class='Value'>π£</span></code> is sort of a "more special" character, as we'll discuss below. Except for <code><span class='Value'>π£</span></code>, every special name is a single character and can't have underscores added to spell it as a modifier. This allows a modifier to be applied to a special name with no spacing, as in <code><span class='Value'>π</span><span class='Modifier'>_m</span></code>, where it couldn't be with ordinary names.</p> +<p>Most special names have a lowercase form for a subject <a href="expression.html#syntactic-role">role</a> and uppercase for a function role. But <code><span class='Value'>π£</span></code> is sort of a "more special" character, as we'll discuss below. The special names other than <code><span class='Value'>π£</span></code> are single characters that don't attach to other letters, allowing <code><span class='Function'>π½</span><span class='Value'>π©</span></code> or <code><span class='Value'>π</span><span class='Modifier'>_m</span></code> to work without spaces; <code><span class='Value'>π£</span></code> is always modifier-valued, so it ought to attach to underscores.</p> <h3 id="arguments"><a class="header" href="#arguments">Arguments</a></h3> <p>The names <code><span class='Value'>π¨</span></code> and <code><span class='Value'>π©</span></code>, and their uppercase spellings, represent function arguments. As the argument to a function is typically data, it's more common to use the lowercase forms for these. Having either of these names turns an immediate block into a function (or an immediate modifier into a deferred one; see the next section). Instead of being evaluated as soon as it appears in the source, a function is evaluated when it's called, with the special names set to appropriate values. Their values can be changed like ordinary variables.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eydjJz3wnZWpfSAiYWJjZCIKeyDwnZWpK+KGqTIg4ouEIDDiiY3wnZWpIH0gMwo0IHsg4p+o8J2VqeKLhC3wnZWo4p+pIH0gNQ==">βοΈ</a><pre> <span class='Brace'>{</span><span class='String'>'c'</span><span class='Function'>=</span><span class='Value'>π©</span><span class='Brace'>}</span> <span class='String'>"abcd"</span> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eydjJz3wnZWpfSAiYWJjZCIKCnsg8J2VqSvihqkyIOKLhCAw4omN8J2VqSB9IDMKCjQgeyDin6jwnZWpLC3wnZWo4p+pIH0gNQ==">βοΈ</a><pre> <span class='Brace'>{</span><span class='String'>'c'</span><span class='Function'>=</span><span class='Value'>π©</span><span class='Brace'>}</span> <span class='String'>"abcd"</span> β¨ 0 0 1 0 β© + <span class='Brace'>{</span> <span class='Value'>π©</span><span class='Function'>+</span><span class='Gets'>β©</span><span class='Number'>2</span> <span class='Separator'>β</span> <span class='Number'>0</span><span class='Function'>β</span><span class='Value'>π©</span> <span class='Brace'>}</span> <span class='Number'>3</span> β¨ 0 5 β© - <span class='Number'>4</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Value'>π©</span><span class='Separator'>β</span><span class='Function'>-</span><span class='Value'>π¨</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> <span class='Number'>5</span> + + <span class='Number'>4</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Value'>π©</span><span class='Separator'>,</span><span class='Function'>-</span><span class='Value'>π¨</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> <span class='Number'>5</span> β¨ 5 Β―4 β© </pre> <p>A function with <code><span class='Value'>π¨</span></code> in its definition doesn't have to be called with two arguments. If it has only one, then <code><span class='Value'>π¨</span></code> is given the special value <a href="expression.html#nothing">Nothing</a>, or <code><span class='Nothing'>Β·</span></code>. This is the only time a variable can ever be Nothing, as an assignment such as <code><span class='Value'>v</span><span class='Gets'>β</span><span class='Nothing'>Β·</span></code> is not allowed.</p> @@ -81,7 +84,7 @@ <span class='Brace'>{</span> <span class='Paren'>(</span><span class='Number'>2</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> <span class='Number'>1</span> Β―1 </pre> -<p>In the second function, <code><span class='Value'>π¨</span></code> behaves just like <code><span class='Nothing'>Β·</span></code>, so that the function <code><span class='Number'>2</span><span class='Function'>Γ</span><span class='Value'>π¨</span></code> is not evaluated and <code><span class='Function'>-</span></code> doesn't have a left argument. It has a similar effect when used as the left argument to a function in a train.</p> +<p>In the second function, <code><span class='Value'>π¨</span></code> behaves just like <code><span class='Nothing'>Β·</span></code>, so that the function <code><span class='Number'>2</span><span class='Function'>Γ</span><span class='Value'>π¨</span></code> is not evaluated and <code><span class='Function'>-</span></code> doesn't have a left argument. It has a similar effect when used as the left argument to a function in a <a href="train.html">train</a>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImFiYyIgeyAo8J2VqOKJjeKMvSkg8J2VqSB9ICJkZWYiCiAgICAgIHsgKPCdlajiiY3ijL0pIPCdlakgfSAiZGVmIg==">βοΈ</a><pre> <span class='String'>"abc"</span> <span class='Brace'>{</span> <span class='Paren'>(</span><span class='Value'>π¨</span><span class='Function'>ββ½</span><span class='Paren'>)</span> <span class='Value'>π©</span> <span class='Brace'>}</span> <span class='String'>"def"</span> ββ β΅"abc @@ -92,7 +95,7 @@ β΅"fed" β </pre> -<p>However, <code><span class='Nothing'>Β·</span></code> can only be used as an argument, and not a list element or operand. Don't use <code><span class='Value'>π¨</span></code> in these ways in a function that could be called monadically. Another potential issue is that <code><span class='Modifier2'>βΈ</span></code> and <code><span class='Modifier2'>β</span></code> don't work the way you might expect.</p> +<p>However, <code><span class='Nothing'>Β·</span></code> can only be used as an argument, and not a list element or operand. Don't use <code><span class='Value'>π¨</span></code> in these ways in a function that could be called monadically. Another <a href="../problems.html#nothing--interacts-strangely-with-before-and-after">potential issue</a> is that <code><span class='Modifier2'>βΈ</span></code> and <code><span class='Modifier2'>β</span></code> don't work the way you might expect.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyDwnZWoIOKLhuKKuC0g8J2VqSB9IDU=">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Value'>π¨</span> <span class='Function'>β</span><span class='Modifier2'>βΈ</span><span class='Function'>-</span> <span class='Value'>π©</span> <span class='Brace'>}</span> <span class='Number'>5</span> 143.4131591025766 </pre> @@ -117,23 +120,23 @@ </pre> <p>The distinction between an immediate and deferred modifier only matters inside the braces. Once defined, the object is simply a modifier that can be called on operands to return a result. For a deferred modifier this result will always be a function; for an immediate modifier it could be anything.</p> <h3 id="self-reference"><a class="header" href="#self-reference">Self-reference</a></h3> -<p>If a block is assigned a name after it is created, this name can be used for recursion:</p> +<p>If a block is assigned a name after it's created, this name can be used for recursion:</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RmFjdCDihpAgeyDwnZWpIMOXICgw4oq4PCnil7Yx4oC/RmFjdCDwnZWpLTEgfQpGYWN0IDcKKMOXwrQxK+KGlSkgNyAgIyBUaGVyZSdzIG9mdGVuIGEgc2ltcGxlciBzb2x1dGlvbiB0aGFuIHJlY3Vyc2lvbg==">βοΈ</a><pre> <span class='Function'>Fact</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Value'>π©</span> <span class='Function'>Γ</span> <span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'><</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Function'>Fact</span> <span class='Value'>π©</span><span class='Function'>-</span><span class='Number'>1</span> <span class='Brace'>}</span> <span class='Function'>Fact</span> <span class='Number'>7</span> 5040 <span class='Paren'>(</span><span class='Function'>Γ</span><span class='Modifier'>Β΄</span><span class='Number'>1</span><span class='Function'>+β</span><span class='Paren'>)</span> <span class='Number'>7</span> <span class='Comment'># There's often a simpler solution than recursion </span>5040 </pre> -<p>This is somewhat unsatisfying because it is external to the function being defined, even though it doesn't depend on outside information. Instead, the special name <code><span class='Function'>π</span></code> can be used to refer to the function it appears in. This allows anonymous recursive functions to be defined.</p> +<p>This is somewhat unsatisfying because the name is external to the function being defined, but the definition shouldn't depend on outside information. Instead, the special name <code><span class='Function'>π</span></code> can be used to refer to the function it appears in. This allows anonymous recursive functions to be defined.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyDwnZWpIMOXICgw4oq4PCnil7Yx4oC/8J2ViiDwnZWpLTEgfSA3">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Value'>π©</span> <span class='Function'>Γ</span> <span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'><</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Function'>π</span> <span class='Value'>π©</span><span class='Function'>-</span><span class='Number'>1</span> <span class='Brace'>}</span> <span class='Number'>7</span> 5040 </pre> -<p>For modifiers, <code><span class='Value'>π£</span></code> refers to the containing modifier. <code><span class='Function'>π</span></code> makes the modifier a deferred modifier like <code><span class='Value'>π¨</span></code> and <code><span class='Value'>π©</span></code> do, and refers to the derived function. For example, this tail-recursive factorial function uses the operand to accumulate a result, a task that is usually done with a second <code><span class='Value'>factorial_helper</span></code> function in elementary Scheme.</p> +<p>For modifiers, <code><span class='Value'>π£</span></code> refers to the containing modifier. <code><span class='Function'>π</span></code> makes the modifier a deferred modifier like <code><span class='Value'>π¨</span></code> and <code><span class='Value'>π©</span></code> do, and refers to the derived function. For example, this tail-recursive factorial function uses the operand to accumulate a result, a task that's usually done with a second <code><span class='Value'>factorial_helper</span></code> function in elementary Scheme (BQN doesn't optimize tail recursion though; it's just shown here as an example).</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RmFjdF9tb2Qg4oaQIDEgeyAoMOKKuDwp4pe24p+o8J2VlywgKPCdlZfDl/CdlakpX/CdlaPin6kg8J2VqS0xIH0KRmFjdF9tb2QgNw==">βοΈ</a><pre> <span class='Function'>Fact_mod</span> <span class='Gets'>β</span> <span class='Number'>1</span> <span class='Brace'>{</span> <span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'><</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Bracket'>β¨</span><span class='Value'>π</span><span class='Separator'>,</span> <span class='Paren'>(</span><span class='Value'>π</span><span class='Function'>Γ</span><span class='Value'>π©</span><span class='Paren'>)</span><span class='Modifier'>_π£</span><span class='Bracket'>β©</span> <span class='Value'>π©</span><span class='Function'>-</span><span class='Number'>1</span> <span class='Brace'>}</span> <span class='Function'>Fact_mod</span> <span class='Number'>7</span> 5040 </pre> -<p>Because <code><span class='Value'>π£</span></code> only ever refers to a 1-modifier or 2-modifer, it can never make sense to refer to it as a function, and the uppercase letter <code><span class='Value'>β</span></code> is not recognized by BQN. In order to allow <code><span class='Value'>π£</span></code> to be spelled as a 1-modifier <code><span class='Modifier'>_π£</span></code> or 2-modifier <code><span class='Modifier2'>_π£_</span></code>, it is treated as an ordinary identifier character, so it must be separated from letters or numbers by spaces.</p> +<p>Because <code><span class='Value'>π£</span></code> only ever refers to a 1-modifier or 2-modifer, it can never make sense to refer to it as a function, and the uppercase letter <code><span class='Value'>β</span></code> is not recognized by BQN. To allow <code><span class='Value'>π£</span></code> to be spelled as a 1-modifier <code><span class='Modifier'>_π£</span></code> or 2-modifier <code><span class='Modifier2'>_π£_</span></code>, it's tokenized as an ordinary identifier character, so it has to be separated from adjacent letters or numbers with a space.</p> <h2 id="block-headers"><a class="header" href="#block-headers">Block headers</a></h2> <p>As a program becomes larger, it often becomes necessary to name inputs to blocks rather than just using special names. It can also become difficult to identify what kind of block is being defined, as it requires scanning through the block for special names. A <em>block header</em>, which is separated from the body of a block by a colon <code><span class='Head'>:</span></code>, specifies the kind of block and can declare names for the block and its inputs.</p> <pre><span class='Function'>Fact</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>F</span> <span class='Value'>n</span><span class='Head'>:</span> @@ -157,20 +160,21 @@ </span><span class='Brace'>{</span> <span class='Function'>F</span> <span class='Modifier2'>_op_</span> <span class='Nothing'>Β·</span><span class='Ligature'>βΏ</span><span class='Value'>val</span><span class='Head'>:</span> <span class='Value'>β¦</span> </pre> -<p>In all cases special names still work just like in a headerless function. In this respect the effect of the header is the same as a series of assignments at the beginning of a function, such as the following translation of the second header above:</p> +<p>In all cases special names still work just like in a headerless function. In this respect, the effect of the header is the same as a series of assignments at the beginning of a function, such as the following translation of the second header above:</p> <pre><span class='Brace'>{</span> <span class='Comment'># Fn _apply β¨a,bβ©: </span> <span class='Function'>Fn</span> <span class='Gets'>β</span> <span class='Function'>π½</span> <span class='Modifier'>_apply</span> <span class='Gets'>β</span> <span class='Modifier'>_π£</span> <span class='Bracket'>β¨</span><span class='Value'>a</span><span class='Separator'>,</span><span class='Value'>b</span><span class='Bracket'>β©</span> <span class='Gets'>β</span> <span class='Value'>π©</span> <span class='Value'>β¦</span> </pre> -<p>Unlike these assignments, the header also constrains what inputs the block can take: a monadic 1-modifier like the one above can't take a right operand or left argument, and consequently its body can't contain <code><span class='Function'>πΎ</span></code> or <code><span class='Value'>π¨</span></code>. Calling it with a left argument, or a right argument that isn't a two-element list, will result in an error.</p> +<p>Unlike these assignments, the header also constrains what inputs the block can take: a monadic 1-modifier like the one above can't take a right operand or left argument, so its body can't contain <code><span class='Function'>πΎ</span></code> or <code><span class='Value'>π¨</span></code>. Calling it with a left argument, or a right argument that isn't a two-element list, will result in an error.</p> <h3 id="destructuring"><a class="header" href="#destructuring">Destructuring</a></h3> -<p>Arguments and operands allow <a href="expression.html#destructuring">destructuring</a> like assignment does. While assignment only tolerates lists of variables, header destructuring also allows constants. The argument must match the given structure, including the constants where they appear, or an error results.</p> +<p>Arguments and operands allow <a href="expression.html#destructuring">destructuring</a> like assignment does. While assignment only tolerates lists of variables, header destructuring also allows constants. For the header to match, the argument must share the given structure, including the constants where they appear.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RGVzdHJ1Y3Qg4oaQIHsg8J2ViiBh4oC/MeKAv+KfqGIswrcsMuKfqTogYeKJjWIgfQpEZXN0cnVjdCAgICAgICA14oC/MeKAv+KfqDcsz4AsMuKfqQ==">βοΈ</a><pre> <span class='Function'>Destruct</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>π</span> <span class='Value'>a</span><span class='Ligature'>βΏ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Bracket'>β¨</span><span class='Value'>b</span><span class='Separator'>,</span><span class='Nothing'>Β·</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Bracket'>β©</span><span class='Head'>:</span> <span class='Value'>a</span><span class='Function'>β</span><span class='Value'>b</span> <span class='Brace'>}</span> <span class='Function'>Destruct</span> <span class='Number'>5</span><span class='Ligature'>βΏ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Bracket'>β¨</span><span class='Number'>7</span><span class='Separator'>,</span><span class='Number'>Ο</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Bracket'>β©</span> β¨ 5 7 β© </pre> +<p>It's also worth noting here that <code><span class='Bracket'>[]</span></code> is a valid destructuring target, matching any length-0 array, even though it can't be used as a value since it's ambiguous. This syntax is also allowed in regular destructuring, but it's not very useful in that case.</p> <h3 id="special-names-in-headers"><a class="header" href="#special-names-in-headers">Special names in headers</a></h3> <p>Any element of a function or modifier header can be left nameless by using the corresponding special name in that position, instead of an identifier. For example, the header <code><span class='Value'>π¨</span> <span class='Function'>π½</span><span class='Modifier2'>_π£_</span><span class='Function'>πΎ</span> <span class='Value'>π©</span><span class='Head'>:</span></code> incorporates as much vagueness as possible. It indicates a deferred 2-modifier, but provides no other information.</p> <p>The name <code><span class='Value'>π¨</span></code> in this context can refer to either a left argument or no left argument, allowing a header with arguments to be used even for an ambiguous function. Recall that <code><span class='Value'>π¨</span></code> is the only token other than <code><span class='Nothing'>Β·</span></code> that can have no value. If an identifier or list is given as the left argument, then the function must be called with a left argument.</p> @@ -181,21 +185,26 @@ </span><span class='Brace'>{</span> <span class='Modifier'>_π£</span><span class='Head'>:</span> <span class='Comment'># 1-Modifier </span><span class='Brace'>{</span> <span class='Modifier2'>_π£_</span><span class='Head'>:</span> <span class='Comment'># 2-Modifier </span></pre> -<p>For immediate blocks, this is the only type of header possible, and it must use an identifier as there is no applicable special name. However, the name can't be used in code: it doesn't make sense to refer to a value while it is still being computed!</p> +<p>For immediate blocks, this is the only type of header possible, and it must use an identifier as there's no applicable special name. However, the name can't be used in code: it doesn't make sense to refer to a value while it's still being computed!</p> <h2 id="multiple-bodies"><a class="header" href="#multiple-bodies">Multiple bodies</a></h2> -<p>Blocks can include more than one body, separated by semicolons <code><span class='Head'>;</span></code>. The body used for a particular evaluation is chosen based on the arguments the the block. One special case is that functions and deferred modifiers can have two headerless bodies (that is, no headers or predicatesβsee below): the first applies when there's one argument and the second when there are two.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=QW1iaXYg4oaQIHsg4p+oMSzwnZWp4p+pIDsg4p+oMizwnZWoLPCdlanin6kgfQpBbWJpdiAnYScKJ2EnIEFtYml2ICdiJw==">βοΈ</a><pre> <span class='Function'>Ambiv</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Bracket'>β¨</span><span class='Number'>2</span><span class='Separator'>,</span><span class='Value'>π¨</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> +<p>Blocks can include more than one body, separated by semicolons <code><span class='Head'>;</span></code>. The body used for a particular evaluation is chosen based on the inputs to the block. One special case is that functions and deferred modifiers can have two headerless bodies (that is, no headers or <a href="#predicates">predicates</a>): the first applies when there's one argument and the second when there are two.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=QW1iaXYg4oaQIHsg4p+oMSzwnZWp4p+pIDsg4p+oMizwnZWoLPCdlanin6kgfQoKQW1iaXYgJ2EnCgonYScgQW1iaXYgJ2In">βοΈ</a><pre> <span class='Function'>Ambiv</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Bracket'>β¨</span><span class='Number'>2</span><span class='Separator'>,</span><span class='Value'>π¨</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> + <span class='Function'>Ambiv</span> <span class='String'>'a'</span> β¨ 1 'a' β© + <span class='String'>'a'</span> <span class='Function'>Ambiv</span> <span class='String'>'b'</span> β¨ 2 'a' 'b' β© </pre> <p>Bodies with headers come before any that don't have them. When a block is called, its headers are checked in order for compatibility with the arguments, and the first body with a compatible header is used.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2FzZUFkZCDihpAgeyAy8J2VijM6MOKAvzUgOyAy8J2VivCdlak64p+oMSwyK/Cdlanin6kgOyDwnZWK8J2VqToy4oC/8J2VqSB9CjIgQ2FzZUFkZCAzCjIgQ2FzZUFkZCA0CiAgQ2FzZUFkZCA0">βοΈ</a><pre> <span class='Function'>CaseAdd</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Number'>3</span><span class='Head'>:</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>5</span> <span class='Head'>;</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Function'>+</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Value'>π©</span> <span class='Brace'>}</span> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2FzZUFkZCDihpAgeyAy8J2VijM6MOKAvzUgOyAy8J2VivCdlak64p+oMSwyK/Cdlanin6kgOyDwnZWK8J2VqToy4oC/8J2VqSB9CgoyIENhc2VBZGQgMwoKMiBDYXNlQWRkIDQKCiAgQ2FzZUFkZCA0">βοΈ</a><pre> <span class='Function'>CaseAdd</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Number'>3</span><span class='Head'>:</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>5</span> <span class='Head'>;</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Function'>+</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Value'>π©</span> <span class='Brace'>}</span> + <span class='Number'>2</span> <span class='Function'>CaseAdd</span> <span class='Number'>3</span> β¨ 0 5 β© + <span class='Number'>2</span> <span class='Function'>CaseAdd</span> <span class='Number'>4</span> β¨ 1 6 β© + <span class='Function'>CaseAdd</span> <span class='Number'>4</span> β¨ 2 4 β© </pre> @@ -214,21 +223,24 @@ </pre> <p>These case-style headers function exactly the same as if they were preceded by <code><span class='Function'>π</span></code>, and can be mixed with other kinds of headers.</p> <h3 id="predicates"><a class="header" href="#predicates">Predicates</a></h3> -<p>Destructuring with a header is quite limited, only allowing matching structure and data with exact equality. A predicate, written with <code><span class='Head'>?</span></code>, allows you to test an arbitrary property before evaluating the rest of the body, and also serves as a limited kind of control flow. It can be thought of as an extension to a header, so that for example the following function requires the argument to have two elements and for the first to be less than the second before using the first body. Otherwise it moves to the next body, which is unconditional.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2hlY2tQYWlyIOKGkCB7IPCdlYrin6hhLGLin6k6IGE8Yj8gIm9rIiA7ICJub3Qgb2siIH0KCkNoZWNrUGFpciDin6gzLDjin6kgICAgIyBGYWlscyBkZXN0cnVjdHVyaW5nCkNoZWNrUGFpciDin6gxLDQsNeKfqSAgIyBOb3QgYSBwYWlyCkNoZWNrUGFpciDin6gzLMKvMeKfqSAgICMgTm90IGFzY2VuZGluZw==">βοΈ</a><pre> <span class='Function'>CheckPair</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>π</span><span class='Bracket'>β¨</span><span class='Value'>a</span><span class='Separator'>,</span><span class='Value'>b</span><span class='Bracket'>β©</span><span class='Head'>:</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span><span class='Head'>?</span> <span class='String'>"ok"</span> <span class='Head'>;</span> <span class='String'>"not ok"</span> <span class='Brace'>}</span> +<p>Destructuring with a header is limited, as it can only match a particular structure or value exactlyβnot, for example, a range of lengths. A predicate, written with <code><span class='Head'>?</span></code>, allows you to test an arbitrary property before evaluating the rest of the body, and also serves as a limited kind of control flow. It can be thought of as an extension to a header. So the following function requires the argument to have two elements and for the first to be less than the second before using the first body. Otherwise it moves to the next body, which is unconditional.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2hlY2tQYWlyIOKGkCB7IPCdlYrin6hhLGLin6k6IGE8Yj8gIm9rIiA7ICJub3Qgb2siIH0KCkNoZWNrUGFpciDin6gzLDjin6kgICAgIyBGYWlscyBkZXN0cnVjdHVyaW5nCgpDaGVja1BhaXIg4p+oMSw0LDXin6kgICMgTm90IGEgcGFpcgoKQ2hlY2tQYWlyIOKfqDMswq8x4p+pICAgIyBOb3QgYXNjZW5kaW5n">βοΈ</a><pre> <span class='Function'>CheckPair</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>π</span><span class='Bracket'>β¨</span><span class='Value'>a</span><span class='Separator'>,</span><span class='Value'>b</span><span class='Bracket'>β©</span><span class='Head'>:</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span><span class='Head'>?</span> <span class='String'>"ok"</span> <span class='Head'>;</span> <span class='String'>"not ok"</span> <span class='Brace'>}</span> <span class='Function'>CheckPair</span> <span class='Bracket'>β¨</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>8</span><span class='Bracket'>β©</span> <span class='Comment'># Fails destructuring </span>"ok" + <span class='Function'>CheckPair</span> <span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>4</span><span class='Separator'>,</span><span class='Number'>5</span><span class='Bracket'>β©</span> <span class='Comment'># Not a pair </span>"not ok" + <span class='Function'>CheckPair</span> <span class='Bracket'>β¨</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>Β―1</span><span class='Bracket'>β©</span> <span class='Comment'># Not ascending </span>"not ok" </pre> -<p>The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. In fact, <code><span class='Head'>?</span></code> functions just like a separator (like <code><span class='Separator'>β</span></code> or <code><span class='Separator'>,</span></code>) with a side effect.</p> +<p>The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. Really, <code><span class='Head'>?</span></code> works just like a separator (like <code><span class='Separator'>β</span></code> or <code><span class='Separator'>,</span></code>) with a side effect.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyBy4oaQ4oy98J2VqSDii4QgJ3QnPeKKkXIgPyByIDsg8J2VqSB9wqggInRlc3Qi4oC/InRoaXMi">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Value'>r</span><span class='Gets'>β</span><span class='Function'>β½</span><span class='Value'>π©</span> <span class='Separator'>β</span> <span class='String'>'t'</span><span class='Function'>=β</span><span class='Value'>r</span> <span class='Head'>?</span> <span class='Value'>r</span> <span class='Head'>;</span> <span class='Value'>π©</span> <span class='Brace'>}</span><span class='Modifier'>Β¨</span> <span class='String'>"test"</span><span class='Ligature'>βΏ</span><span class='String'>"this"</span> β¨ "tset" "this" β© </pre> -<p>So <code><span class='Value'>r</span></code> is the reversed argument, and if its first character (the last one in <code><span class='Value'>π©</span></code>) is <code><span class='String'>'t'</span></code> then it returns <code><span class='Value'>r</span></code>, and otherwise we abandon that line of reasoning and return <code><span class='Value'>π©</span></code>. This sounds a lot like an if statement. And <code><span class='Brace'>{</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span> <span class='Head'>?</span> <span class='Value'>a</span> <span class='Head'>;</span> <span class='Value'>b</span> <span class='Brace'>}</span></code>, which computes <code><span class='Value'>a</span><span class='Function'>β</span><span class='Value'>b</span></code> the hard way, shows how the syntax can be similar to a ternary operator. This is an immediate block with multiple bodies, something that makes sense with predicates but not headers. But <code><span class='Head'>?;</span></code> offers more possibilities. It can support any number of options, with multiple tests for each oneβthe structure below is "if _ and _ then _; else if _ then _; else _".</p> +<p>So <code><span class='Value'>r</span></code> is the reversed argument, and if its first character (the last one in <code><span class='Value'>π©</span></code>) is <code><span class='String'>'t'</span></code> then it returns <code><span class='Value'>r</span></code>, and otherwise we abandon that line of reasoning and return <code><span class='Value'>π©</span></code>.</p> +<p>This sounds a lot like an if statement. And <code><span class='Brace'>{</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span> <span class='Head'>?</span> <span class='Value'>a</span> <span class='Head'>;</span> <span class='Value'>b</span> <span class='Brace'>}</span></code>, which computes <code><span class='Value'>a</span><span class='Function'>β</span><span class='Value'>b</span></code> the hard way, shows how the syntax can be similar to a ternary operator. This is an immediate block with multiple bodies, something that makes sense with predicates but not headers. But <code><span class='Head'>?;</span></code> offers more possibilities. It can support any number of options, with multiple tests for each oneβthe structure below is "if _ and _ then _; else if _ then _; else _".</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=VGhpbmcg4oaQIHsg8J2VqeKJpTM/IPCdlaniiaQ4PyAyfPCdlakgOyDwnZWpPTA/IEAgOyDiiJ4gfQoKKOKKoiDiiY0gVGhpbmfCqCkg4oaVMTAgICMgVGFibGUgb2YgYXJndW1lbnRzIGFuZCByZXN1bHRz">βοΈ</a><pre> <span class='Function'>Thing</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Value'>π©</span><span class='Function'>β₯</span><span class='Number'>3</span><span class='Head'>?</span> <span class='Value'>π©</span><span class='Function'>β€</span><span class='Number'>8</span><span class='Head'>?</span> <span class='Number'>2</span><span class='Function'>|</span><span class='Value'>π©</span> <span class='Head'>;</span> <span class='Value'>π©</span><span class='Function'>=</span><span class='Number'>0</span><span class='Head'>?</span> <span class='String'>@</span> <span class='Head'>;</span> <span class='Number'>β</span> <span class='Brace'>}</span> <span class='Paren'>(</span><span class='Function'>β’</span> <span class='Function'>β</span> <span class='Function'>Thing</span><span class='Modifier'>Β¨</span><span class='Paren'>)</span> <span class='Function'>β</span><span class='Number'>10</span> <span class='Comment'># Table of arguments and results @@ -237,7 +249,7 @@ @ β β 1 0 1 0 1 0 β β </pre> -<p>This structure is still constrained by the rules of block bodies: each instance of <code><span class='Head'>;</span></code> is a separate scope, so that variables defined before a <code><span class='Head'>?</span></code> don't survive past the <code><span class='Head'>;</span></code>.</p> +<p>This structure is still controlled by the rules of block bodies: each instance of <code><span class='Head'>;</span></code> is a separate scope, so that variables defined before a <code><span class='Head'>?</span></code> don't survive past the <code><span class='Head'>;</span></code>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyAwPW7ihpDiiaDwnZWpID8g4oieIDsgbiB9ICJhYmMi">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Number'>0</span><span class='Function'>=</span><span class='Value'>n</span><span class='Gets'>β</span><span class='Function'>β </span><span class='Value'>π©</span> <span class='Head'>?</span> <span class='Number'>β</span> <span class='Head'>;</span> <span class='Value'>n</span> <span class='Brace'>}</span> <span class='String'>"abc"</span> <span class='Error'>Error: Undefined identifier</span> </pre> diff --git a/docs/doc/choose.html b/docs/doc/choose.html index 2bcaa223..d76da055 100644 --- a/docs/doc/choose.html +++ b/docs/doc/choose.html @@ -5,16 +5,16 @@ </head> <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div> <h1 id="choose"><a class="header" href="#choose">Choose</a></h1> -<p>The 2-modifier Choose (<code><span class='Modifier2'>βΆ</span></code>) applies one function from a list <code><span class='Value'>π</span></code>, based on a selection function <code><span class='Function'>π½</span></code> that returns an index. It's a combinator form of <a href="pick.html">Pick</a> (<code><span class='Function'>β</span></code>), so that <code><span class='Brace'>{</span><span class='Value'>f</span><span class='Gets'>β</span><span class='Paren'>(</span><span class='Value'>π¨</span><span class='Function'>π½</span><span class='Value'>π©</span><span class='Paren'>)</span><span class='Function'>β</span><span class='Value'>π</span> <span class='Separator'>β</span> <span class='Value'>π¨</span><span class='Function'>F</span><span class='Value'>π©</span><span class='Brace'>}</span></code> is a complete definition. For example, the function below subtracts 1 from an argument if negative and adds 1 if positive.</p> +<p>The 2-modifier Choose (<code><span class='Modifier2'>βΆ</span></code>) applies one function from a list <code><span class='Value'>π</span></code>, based on the selecting index returned by a function <code><span class='Function'>π½</span></code>. It's a combinator form of <a href="pick.html">Pick</a> (<code><span class='Function'>β</span></code>), so that <code><span class='Brace'>{</span><span class='Value'>f</span><span class='Gets'>β</span><span class='Paren'>(</span><span class='Value'>π¨</span><span class='Function'>π½</span><span class='Value'>π©</span><span class='Paren'>)</span><span class='Function'>β</span><span class='Value'>π</span> <span class='Separator'>β</span> <span class='Value'>π¨</span><span class='Function'>F</span><span class='Value'>π©</span><span class='Brace'>}</span></code> is a complete definition. For example, the function below subtracts 1 from its argument if negative and adds 1 if positive.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MOKKuOKJpOKXtuKfqC3in5wxLCAr4p+cMeKfqcKoIDPigL/CrzHigL81">βοΈ</a><pre> <span class='Number'>0</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'>1</span><span class='Separator'>,</span> <span class='Function'>+</span><span class='Modifier2'>β</span><span class='Number'>1</span><span class='Bracket'>β©</span><span class='Modifier'>Β¨</span> <span class='Number'>3</span><span class='Ligature'>βΏ</span><span class='Number'>Β―1</span><span class='Ligature'>βΏ</span><span class='Number'>5</span> β¨ 4 Β―2 6 β© </pre> -<p>Here the selection function <code><span class='Function'>π½</span></code> is <code><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'>β€</span></code>, while <code><span class='Value'>π</span></code> is a list of two functions <code><span class='Bracket'>β¨</span><span class='Function'>-</span><span class='Modifier2'>β</span><span class='Number'>1</span><span class='Separator'>,</span> <span class='Function'>+</span><span class='Modifier2'>β</span><span class='Number'>1</span><span class='Bracket'>β©</span></code>. On the first argument, <code><span class='Number'>3</span></code>, <code><span class='Function'>π½</span><span class='Number'>3</span></code> is <code><span class='Number'>0</span><span class='Function'>β€</span><span class='Number'>3</span></code>, or <code><span class='Number'>1</span></code>, so the function <code><span class='Function'>+</span><span class='Modifier2'>β</span><span class='Number'>1</span></code> from <code><span class='Value'>π</span></code> is chosen. The use of array indices means "false" comes first in <code><span class='Value'>π</span></code> and "true" comes second, which is backwards relative to if-else constructs in most programming languages (including BQN's own predicates). When using a comparison for <code><span class='Function'>π½</span></code> I strongly prefer to phrase it as <code><span class='Value'>n</span><span class='Modifier2'>βΈ</span><span class='Function'><</span></code> or <code><span class='Value'>n</span><span class='Modifier2'>βΈ</span><span class='Function'>β€</span></code> so that smaller values go through the first one and larger functions go through the second. This doesn't apply so much when comparing two arguments since one is smaller but the other's larger, so I don't have an easy technique for that.</p> +<p>Here the selection function <code><span class='Function'>π½</span></code> is <code><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'>β€</span></code>, while <code><span class='Value'>π</span></code> is a list of two functions <code><span class='Bracket'>β¨</span><span class='Function'>-</span><span class='Modifier2'>β</span><span class='Number'>1</span><span class='Separator'>,</span> <span class='Function'>+</span><span class='Modifier2'>β</span><span class='Number'>1</span><span class='Bracket'>β©</span></code>. On the first argument, <code><span class='Number'>3</span></code>, <code><span class='Function'>π½</span><span class='Number'>3</span></code> is <code><span class='Number'>0</span><span class='Function'>β€</span><span class='Number'>3</span></code>, or <code><span class='Number'>1</span></code>, so the function <code><span class='Function'>+</span><span class='Modifier2'>β</span><span class='Number'>1</span></code> from <code><span class='Value'>π</span></code> is chosen. The use of array indices means "false" comes first in <code><span class='Value'>π</span></code> and "true" comes second, which is backwards relative to if-else constructs in most programming languages (including BQN's own <a href="block.html#predicates">predicates</a>). When using a comparison for <code><span class='Function'>π½</span></code> I strongly prefer to phrase it as <code><span class='Value'>n</span><span class='Modifier2'>βΈ</span><span class='Function'><</span></code> or <code><span class='Value'>n</span><span class='Modifier2'>βΈ</span><span class='Function'>β€</span></code> so that smaller values go through the first one and larger functions go through the second. This doesn't apply so much when comparing two arguments since one is smaller but the other's larger, so I don't have an easy answer for that.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MiA+4pe24oqj4oC/4oqiIDYgICMgQSBtaW5pbXVtIGZ1bmN0aW9uICjijIop">βοΈ</a><pre> <span class='Number'>2</span> <span class='Function'>></span><span class='Modifier2'>βΆ</span><span class='Function'>β£</span><span class='Ligature'>βΏ</span><span class='Function'>β’</span> <span class='Number'>6</span> <span class='Comment'># A minimum function (β) </span>2 </pre> <p>The advantage of using an index is that Choose works with any number of options.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Rm4g4oaQICjiipEicnRkIuKKkuKKjynil7bin6jijL0sIDHiirjihpEsIDHiirjihpMsIOKKouKfqSAgIyBSZXZlcnNlLCB0YWtlIDEsIGRyb3AgMQoKRm4gInIxMjMiCgpGbiAiZDEyMyIKCkZuICIxMjMiICAjIERlZmF1bHQ=">βοΈ</a><pre> <span class='Function'>Fn</span> <span class='Gets'>β</span> <span class='Paren'>(</span><span class='Function'>β</span><span class='String'>"rtd"</span><span class='Function'>ββ</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Bracket'>β¨</span><span class='Function'>β½</span><span class='Separator'>,</span> <span class='Number'>1</span><span class='Modifier2'>βΈ</span><span class='Function'>β</span><span class='Separator'>,</span> <span class='Number'>1</span><span class='Modifier2'>βΈ</span><span class='Function'>β</span><span class='Separator'>,</span> <span class='Function'>β’</span><span class='Bracket'>β©</span> <span class='Comment'># Reverse, take 1, drop 1 +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Rm4g4oaQICjiipEicnRkIuKKkOKKjynil7bin6jijL0sIDHiirjihpEsIDHiirjihpMsIOKKouKfqSAgIyBSZXZlcnNlLCB0YWtlIDEsIGRyb3AgMQoKRm4gInIxMjMiCgpGbiAiZDEyMyIKCkZuICIxMjMiICAjIERlZmF1bHQ=">βοΈ</a><pre> <span class='Function'>Fn</span> <span class='Gets'>β</span> <span class='Paren'>(</span><span class='Function'>β</span><span class='String'>"rtd"</span><span class='Function'>ββ</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Bracket'>β¨</span><span class='Function'>β½</span><span class='Separator'>,</span> <span class='Number'>1</span><span class='Modifier2'>βΈ</span><span class='Function'>β</span><span class='Separator'>,</span> <span class='Number'>1</span><span class='Modifier2'>βΈ</span><span class='Function'>β</span><span class='Separator'>,</span> <span class='Function'>β’</span><span class='Bracket'>β©</span> <span class='Comment'># Reverse, take 1, drop 1 </span> <span class='Function'>Fn</span> <span class='String'>"r123"</span> "321r" @@ -25,6 +25,6 @@ <span class='Function'>Fn</span> <span class='String'>"123"</span> <span class='Comment'># Default </span>"123" </pre> -<p>The selection function in <code><span class='Function'>Fn</span></code> uses <a href="search.html#index-of">Index of</a> (<code><span class='Function'>β</span></code>) to find the index of the first character in the list <code><span class='String'>"rtd"</span></code>. An extra value in <code><span class='Value'>π</span></code> serves as a default function if it's none of those, since the result of <code><span class='Function'>π½</span></code> is <code><span class='Number'>3</span></code> in that case. A similar function that's often useful is <a href="order.html#bins">Bins</a>, for grouping inputs into intervals rather than by exact matching.</p> +<p>The selection function in <code><span class='Function'>Fn</span></code> uses <a href="search.html#index-of">Index of</a> (<code><span class='Function'>β</span></code>) to find the index of the first character in the list <code><span class='String'>"rtd"</span></code>. An extra value in <code><span class='Value'>π</span></code> serves as a default function if it's none of those, since the result of <code><span class='Function'>π½</span></code> is <code><span class='Number'>3</span></code> in that case. A similar function that's often useful is <a href="order.html#bins">Bins</a>, for grouping inputs into intervals rather than by exact matching.</p> <p>Choose is necessary for <a href="tacit.html">tacit</a> programming, but tacit programming is not necessary to be an effective BQN programmer! Consider using block features like <a href="block.html#predicates">predicates</a> when Choose isn't working with your program's flow.</p> <p>Because Choose is based on <a href="pick.html">Pick</a>, it retains the features of negative, multidimensional, and multiple selection. Negative indexing might make sense if there's some special <code><span class='Number'>Β―1</span></code> value, and if the options naturally form an array, multidimensional indexing is pretty neat. Selecting multiple values from <code><span class='Value'>π</span></code>, which happens if the result of <code><span class='Function'>π½</span></code> is an array of arrays, is never useful because the array result from <code><span class='Function'>π½</span></code> acts as a constant function. It's much clearer to express it as <code><span class='Function'>π½β</span><span class='Value'>π</span><span class='Modifier'>Λ</span></code>.</p> diff --git a/docs/doc/compose.html b/docs/doc/compose.html index 7a8da224..eec1877e 100644 --- a/docs/doc/compose.html +++ b/docs/doc/compose.html @@ -69,7 +69,7 @@ </g> </svg> -<p>Atop and Over are 2-modifiers that extend the idea of "apply this, then that" in two different ways. They're modelled after the mathematical notation fβg to compose two functions, and both do the same thing when there's one argument: <code><span class='Function'>F</span><span class='Modifier2'>β</span><span class='Function'>G</span> <span class='Value'>x</span></code> or <code><span class='Function'>F</span><span class='Modifier2'>β</span><span class='Function'>G</span> <span class='Value'>x</span></code> is <code><span class='Function'>F</span> <span class='Function'>G</span> <span class='Value'>x</span></code>.</p> +<p>Atop and Over are 2-modifiers that extend the idea of "apply this, then that" in two different ways. They're modelled after the mathematical notation fβg to compose two functions, and both do the same thing when there's one argument: either <code><span class='Function'>F</span><span class='Modifier2'>β</span><span class='Function'>G</span> <span class='Value'>x</span></code> or <code><span class='Function'>F</span><span class='Modifier2'>β</span><span class='Function'>G</span> <span class='Value'>x</span></code> is <code><span class='Function'>F</span> <span class='Function'>G</span> <span class='Value'>x</span></code>.</p> <table> <thead> <tr> @@ -99,7 +99,7 @@ </table> <p>When there are two arguments, we might say Atop treats the right operand <code><span class='Function'>πΎ</span></code> as primary and Over treats <code><span class='Function'>π½</span></code> as primaryβthe primary operand becomes dyadic while the other is always monadic. Atop applies <code><span class='Function'>πΎ</span></code> directly, making it more like mathematical composition if we suppose that <code><span class='Function'>πΎ</span></code> is a function that can take a pair of arguments. Over instead makes two calls to apply <code><span class='Function'>πΎ</span></code> separately to both arguments, then passes the results to <code><span class='Function'>π½</span></code>.</p> <h2 id="atop"><a class="header" href="#atop">Atop</a></h2> -<p>Of the two modifiers on this page, Atop is more common but less impactful. The composition <code><span class='Function'>F</span><span class='Modifier2'>β</span><span class='Function'>G</span></code> is equivalent to the 2-<a href="train.html">train</a> <code><span class='Function'>F</span> <span class='Function'>G</span></code> (the trains page has hints on when you'd choose one or the other). Its definition <code><span class='Brace'>{</span><span class='Function'>F</span><span class='Value'>π¨</span><span class='Function'>G</span><span class='Value'>π©</span><span class='Brace'>}</span></code> means that <code><span class='Function'>G</span></code> is applied to one or two arguments and <code><span class='Function'>F</span></code> is applied monadically to the result. It could be considered a "default way" to compose two functions. Keeps <a href="tacit.html">tacit</a> programming syntax running smoothly, without making noise about it. Not like that busybody <code><span class='Modifier2'>βΈ</span></code>. Some examples:</p> +<p>Of the two modifiers on this page, Atop is more common but less impactful. The composition <code><span class='Function'>F</span><span class='Modifier2'>β</span><span class='Function'>G</span></code> is equivalent to the 2-<a href="train.html">train</a> <code><span class='Function'>F</span> <span class='Function'>G</span></code> (the trains page has hints on when you'd choose one or the other). Its definition <code><span class='Brace'>{</span><span class='Function'>F</span><span class='Value'>π¨</span><span class='Function'>G</span><span class='Value'>π©</span><span class='Brace'>}</span></code> means that <code><span class='Function'>G</span></code> is applied to one or two arguments and <code><span class='Function'>F</span></code> is applied monadically to the result. It's sort of a "default way" to compose two functions. Keeps <a href="tacit.html">tacit</a> programming syntax running smoothly, without making noise about it. Not like that busybody <code><span class='Modifier2'>βΈ</span></code>. Some examples:</p> <p><code><span class='Function'>β</span><span class='Modifier2'>β</span><span class='Function'>β </span></code> is useful with one argument: <code><span class='Function'>ββ </span><span class='Value'>l</span></code> is a list of indices for <code><span class='Value'>l</span></code>.</p> <p><code><span class='Function'>β</span><span class='Modifier2'>β</span><span class='Function'>Γ·</span></code> is useful with two arguments: <code><span class='Function'>β</span><span class='Value'>a</span><span class='Function'>Γ·</span><span class='Value'>b</span></code> is the integer part when dividing <code><span class='Value'>a</span></code> by <code><span class='Value'>b</span></code>, often paired with the <a href="arithmetic.html#additional-arithmetic">remainder</a> <code><span class='Value'>b</span><span class='Function'>|</span><span class='Value'>a</span></code>.</p> <p><code><span class='Function'>β</span><span class='Modifier2'>β</span><span class='Function'>β</span></code> is useful with one or two arguments. From right to left, we have <a href="selfcmp.html#classify">Classify</a>/<a href="search.html#index-of">Index-of</a> (<code><span class='Function'>β</span></code>) to convert values to indices, and <a href="group.html">Group Indices</a> to group the indices. Er, that sounds good but what it <em>actually</em> does is to group indices of Group's argument, which correspond to indices of the original <code><span class='Value'>π©</span></code>, according to their values as returned by <code><span class='Function'>β</span></code>. Without a left argument, this means indices of <code><span class='Value'>π©</span></code> are grouped corresponding to <code><span class='Function'>β·</span><span class='Value'>π©</span></code>, and if <code><span class='Value'>π¨</span></code> is provided the groups correspond to <code><span class='Value'>π¨</span></code> instead.</p> @@ -112,7 +112,7 @@ <h2 id="over"><a class="header" href="#over">Over</a></h2> <p>Once you get used to Over, it's painful to go without it. I'd use it all the time in C if I could.</p> <p>Usually Over is used just for the dyadic meaning. If you have a composition that only works with one argument it's typical to write it with Atop (<code><span class='Modifier2'>β</span></code>). And cases that work with one or two arguments do come up from time to time, but they're fairly rare, so the examples below are just for two arguments.</p> -<p>A classic is the function <code><span class='Function'>β‘</span><span class='Modifier2'>β</span><span class='Function'>β§</span></code>, which tests whether <code><span class='Value'>π¨</span></code> is a reordering of <code><span class='Value'>π©</span></code>. The idea is to sort both arrays with <code><span class='Function'>β§</span></code> to remove the ordering information</p> +<p>A classic is the function <code><span class='Function'>β‘</span><span class='Modifier2'>β</span><span class='Function'>β§</span></code>, which tests whether <code><span class='Value'>π¨</span></code> is a reordering of <code><span class='Value'>π©</span></code>. The idea is to sort both arrays with <code><span class='Function'>β§</span></code> to remove the ordering information, then see if they match.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=IkJRTiIg4omh4peL4oinICJRTkIiCiJCUU4iIOKJoeKXi+KIpyAiQkJRIg==">βοΈ</a><pre> <span class='String'>"BQN"</span> <span class='Function'>β‘</span><span class='Modifier2'>β</span><span class='Function'>β§</span> <span class='String'>"QNB"</span> 1 <span class='String'>"BQN"</span> <span class='Function'>β‘</span><span class='Modifier2'>β</span><span class='Function'>β§</span> <span class='String'>"BBQ"</span> |
