diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/spec/index.html | 2 | ||||
| -rw-r--r-- | docs/spec/primitive.html | 8 |
2 files changed, 9 insertions, 1 deletions
diff --git a/docs/spec/index.html b/docs/spec/index.html index 391d34b4..71d7c6f6 100644 --- a/docs/spec/index.html +++ b/docs/spec/index.html @@ -6,7 +6,7 @@ <div class="nav"><a href="https://github.com/mlochbaum/BQN">BQN</a> / <a href="../index.html">main</a></div> <h1 id="bqn-specification">BQN specification</h1> <p>This directory gives a specification for BQN. The specification differs from the <a href="../doc/index.html">documentation</a> in that its purpose is only to describe the exact details of BQN's operation in the most quickly accessible way, rather than to explain the core ideas of BQN functionality and how it might be used.</p> -<p>All normative sections of the core BQN specification (that is, excluding system-provided values) are now complete, but the non-normative commentary on primitive definitions is still missing a few sections.</p> +<p>The core of BQN, which excludes system-provided values, is now completely specified, although the spec will continue to be edited further to improve clarity and cover edge cases that were missed initially.</p> <p>The BQN specification consists of the following documents:</p> <ul> <li><a href="types.html">Types</a></li> diff --git a/docs/spec/primitive.html b/docs/spec/primitive.html index 30549201..02b856be 100644 --- a/docs/spec/primitive.html +++ b/docs/spec/primitive.html @@ -128,6 +128,14 @@ <p><strong>First Cell</strong> (<code><span class='Function'>β</span></code>) selects the initial major cell of <code><span class='Value'>π©</span></code>, giving an error if <code><span class='Value'>π©</span></code> has rank 0 or length 0.</p> <p><strong>Group</strong> (<code><span class='Function'>β</span></code>) performs an opposite operation to Select, so that <code><span class='Value'>π¨</span></code> specifies not the argument index that result values come from, but the result index that argument values go to. The result rank is <code><span class='Function'>β </span><span class='Value'>π¨</span></code>, and each result element has rank <code><span class='Number'>1</span><span class='Function'>+</span><span class='Paren'>(</span><span class='Function'>=</span><span class='Value'>π©</span><span class='Paren'>)</span><span class='Function'>-+</span><span class='Modifier'>Β΄</span><span class='Function'>=</span><span class='Modifier'>Β¨</span><span class='Value'>π¨</span></code>. The result element contains the minimal list of cells so that each cell of <code><span class='Value'>π©</span></code> appears in the corresponding element of <code><span class='Value'>π¨</span><span class='Function'>β</span><span class='Value'>π¨</span><span class='Function'>β</span><span class='Value'>π©</span></code>, in index order. <strong>Group Indices</strong> treats its argument <code><span class='Value'>π©</span></code> as a left argument for Group and uses a right argument made up of indices, with the definition <code><span class='Function'>β</span><span class='Modifier2'>β</span><span class='Paren'>(</span><span class='Function'>ββ </span><span class='Modifier2'>β</span><span class='Number'>1</span><span class='Paren'>)</span></code>.</p> <p><strong>Range</strong> (<code><span class='Function'>β</span></code>) is extended to apply to a list of natural numbers, in addition to the provided case of a single natural number (an enclosed natural number <code><span class='Value'>π©</span></code> should still result in an error). For a list <code><span class='Value'>π©</span></code>, the result is an array of shape <code><span class='Value'>π©</span></code> in which the value at a given index is that index, as a list of natural numbers. That is, <code><span class='Value'>i</span><span class='Function'>β‘</span><span class='Value'>i</span><span class='Function'>ββ</span><span class='Value'>π©</span></code> for any list of natural numbers <code><span class='Value'>i</span></code> with <code><span class='Function'>β§</span><span class='Modifier'>Β΄</span><span class='Value'>i</span><span class='Function'><</span><span class='Value'>π©</span></code>.</p> +<p><strong>Indices</strong> (<code><span class='Function'>/</span></code>) applies to a list of natural numbers, and returns a list of natural numbers. The result contains <code><span class='Value'>i</span><span class='Function'>β</span><span class='Value'>π©</span></code> copies of each natural number index <code><span class='Value'>i</span></code> for <code><span class='Value'>π©</span></code>, in increasing order.</p> +<h3 id="structural-manipulation">Structural manipulation</h3> +<p>Monadic structural functions work on the first axis of the argument, so they require it to have rank at least 1. <strong>Reverse</strong> (<code><span class='Function'>β½</span></code>) reverses the ordering of the major cells of <code><span class='Value'>π©</span></code>. <strong>Nudge</strong> (<code><span class='Function'>Β»</span></code>) shifts them forward, removing the last and placing a major cell made up of fill elements at the beginning, while <strong>Nudge Back</strong> (<code><span class='Function'>Β«</span></code>) does the same in the reverse direction, so it removes the first cell and places fills at the end. <strong>Prefixes</strong> (<code><span class='Function'>β</span></code>) and <strong>Suffixes</strong> (<code><span class='Function'>β</span></code>) each return lists with length one higher than <code><span class='Value'>π©</span></code>, whose elements are arrays with the same rank as <code><span class='Value'>π©</span></code>. For Prefixes, the element of the result at index <code><span class='Value'>i</span></code> contains the first <code><span class='Value'>i</span></code> major cells of <code><span class='Value'>π©</span></code> in order, and for Suffixes, it contains all but these major cells.</p> +<p>The remainder of the functions discussed in this section are dyadic. There are four functions for which <code><span class='Value'>π¨</span></code> is a list of whole numbersβbut an atomic number or enclosed number is also permitted, and treated as a 1-element listβand its elements are matched with leading axes of <code><span class='Value'>π©</span></code>. These functions independently manipulate each axis: one way to define such a process is to consider lists running along the axis, where every element of the index is fixed except one. A change to this axis retains the fixed indices, but can move elements from one location to another along the variable index, add fill elements, or split the axis into two axes. A change to a different axis can rearrange these lists along the original axis, but can't affect the placement of elements within them. In the reference implementations, working on leading axes is accomplished using the Cells (<code><span class='Modifier'>Λ</span></code>) modifier recursively, so that action on the first axes doesn't use Cells, on the next is affected by Cells once, then twice, and so on.</p> +<p><strong>Rotate</strong> (<code><span class='Function'>β½</span></code>) is the simplest of these four functions: each element of <code><span class='Value'>π¨</span></code> gives an amount to rotate the corresponding axis, where a rotation of <code><span class='Value'>r</span></code> moves the element at index <code><span class='Value'>i</span><span class='Function'>+</span><span class='Value'>r</span></code> to <code><span class='Value'>i</span></code> when all indices are taken modulo the length of the axis. <strong>Windows</strong> (<code><span class='Function'>β</span></code>) splits each axis of <code><span class='Value'>π©</span></code> that corresponds to an element of <code><span class='Value'>π¨</span></code> in two, so that the result has one set of axes corresponding to elements of <code><span class='Value'>π¨</span></code>, then another, then the unchanged trailing axes. The second set of axes has lengths given by <code><span class='Value'>π¨</span></code> (which must consist of natural numbers), while the first has lengths <code><span class='Value'>s</span><span class='Function'>Β¬</span><span class='Value'>π¨</span></code>, where <code><span class='Value'>s</span></code> contains the lengths of leading axes of <code><span class='Value'>π©</span></code>. Position <code><span class='Value'>i</span></code> in the first set of axes and <code><span class='Value'>j</span></code> in the second corresponds to <code><span class='Value'>i</span><span class='Function'>+</span><span class='Value'>j</span></code> in the argument, so that fixing one of these positions and varying the other gives a slice of the argument. In both Rotate and Windows, the length of <code><span class='Value'>π¨</span></code> is at most the rank of <code><span class='Value'>π©</span></code>.</p> +<p><strong>Take</strong> (<code><span class='Function'>β</span></code>) offers several possibilities. The absolute value of <code><span class='Value'>π¨</span></code> gives the final lengths of the axes in the result. It may be positive to indicate that the axis aligns with <code><span class='Value'>π©</span></code> at the beginning, or negative to indicate it aligns at the end. A zero value gives no result elements, so there is no need to consider alignment. If the absolute value of an element of <code><span class='Value'>π¨</span></code> is smaller than or equal to the corresponding length in <code><span class='Value'>π©</span></code>, then the first or last few elements are taken along that axis. If it is larger, then instead fill elements are added to the end (if positive) or beginning (if negative) to make up the difference in length. <strong>Drop</strong> (<code><span class='Function'>β</span></code>) gives <code><span class='Value'>π¨</span></code> a similar meaning, but excludes all elements that Take includes (maintaining the order of the retained ones). The result of Drop never uses fill elements. In a case where Take would use fill elements, it would include all positions from <code><span class='Value'>π©</span></code>, so Drop should include none of them, and the result will have length <code><span class='Number'>0</span></code> for that axis. Take and Drop are extended to allow an argument with length greater than the rank of <code><span class='Value'>π©</span></code>. In this case leading length-1 axes are added to <code><span class='Value'>π©</span></code> so that its rank matches <code><span class='Value'>π¨</span></code> before taking or dropping. If <code><span class='Value'>π©</span></code> is an atom, it is always enclosed to an array first, even if <code><span class='Value'>π¨</span></code> is empty.</p> +<p><strong>Replicate</strong> (<code><span class='Function'>/</span></code>) is similar to the four dyadic structural functions above, but <code><span class='Value'>π¨</span></code> gives a list of containing <em>lists</em> of natural numbers, or plain or enclosed natural numbers, instead of a simple list. If <code><span class='Value'>π¨</span></code> has depth less than <code><span class='Number'>2</span></code>, it's considered to be a single value corresponding to one axis of <code><span class='Value'>π©</span></code>, while if it has depth <code><span class='Number'>2</span></code> then it's a list of values. If <code><span class='Value'>π¨</span></code> is the empty list <code><span class='Bracket'>β¨β©</span></code> then it is defined to be in the second case despite having a depth of <code><span class='Number'>1</span></code>. On a single axis of <code><span class='Value'>π©</span></code> the corresponding value <code><span class='Value'>r</span></code> from <code><span class='Value'>π¨</span></code> is either a list or a unit: if it's a unit then it is repeated to match the length of that axis of <code><span class='Value'>π©</span></code>, and if it's a list it must already have the same length as that axis. Each number in <code><span class='Value'>r</span></code> now specifies the number of times to repeat the corresponding position in <code><span class='Value'>π©</span></code>. This is equivalent to calling Indices on <code><span class='Value'>r</span></code> and using the result for selection.</p> +<p><strong>Shift Before</strong> (<code><span class='Function'>Β»</span></code>) and <strong>Shift After</strong> (<code><span class='Function'>Β«</span></code>) are derived from Join To and share most of its behavior. The difference is that only a portion of the result of Join To is returned, matching the length of <code><span class='Value'>π©</span></code>. This portion comes from the beginning for Shift Before and the end for Shift After. The only difference in conditions between the shift functions and Join To is that Join To allows <code><span class='Value'>π©</span></code> to have smaller rank than <code><span class='Value'>π¨</span></code> while for shifting it must have the same or greater rank.</p> <h3 id="searching">Searching</h3> <p><strong>Match</strong> (<code><span class='Function'>β‘</span></code>) indicates whether two values are considered equivalent. It always returns 0 or 1, and never causes an error. If both arguments are atoms then it is identical to <code><span class='Function'>=</span></code>, and if one is an atom and the other an array then it returns 0. If both arguments are arrays then it returns 1 only if they have the same shape and all pairs of corresponding elements match. Fill elements aren't taken into account, so that arrays that match might still differ in behavior. <strong>Not Match</strong> simply returns the complement of Match, <code><span class='Function'>Β¬β‘</span></code>.</p> <p>Monadic search functions compare the major cells of <code><span class='Value'>π©</span></code> to each other. <code><span class='Value'>π©</span></code> must have rank at least 1. Except for Deduplicate (<code><span class='Function'>β·</span></code>), the result is a list of numbers with the same length as <code><span class='Value'>π©</span></code>.</p> |
