diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-02-02 22:04:48 -0500 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-02-02 22:07:54 -0500 |
| commit | ad582b5ef4184e26be86ef61be60c28e90b0bb7d (patch) | |
| tree | c2447d76d70cc5ed446e9a00f1451b07510523ca /docs/doc | |
| parent | f6899943601e9b9787c33f6eccfc5eb3ecb91be9 (diff) | |
Documentation for Match, and atom equality
Diffstat (limited to 'docs/doc')
| -rw-r--r-- | docs/doc/index.html | 1 | ||||
| -rw-r--r-- | docs/doc/match.html | 93 | ||||
| -rw-r--r-- | docs/doc/primitive.html | 4 |
3 files changed, 96 insertions, 2 deletions
diff --git a/docs/doc/index.html b/docs/doc/index.html index 52f09365..0cda7fa8 100644 --- a/docs/doc/index.html +++ b/docs/doc/index.html @@ -31,6 +31,7 @@ <li><a href="group.html">Group</a> (<code><span class='Function'>⊔</span></code>)</li> <li><a href="join.html">Join and Join To</a> (<code><span class='Function'>∾</span></code>)</li> <li><a href="logic.html">Logical functions</a> (<code><span class='Function'>∧∨¬</span></code>)</li> +<li><a href="match.html">Match</a> (<code><span class='Function'>≡≢</span></code>)</li> <li><a href="prefixes.html">Prefixes and Suffixes</a> (<code><span class='Function'>↑↓</span></code>)</li> <li><a href="shift.html">Shift functions</a> (<code><span class='Function'>»«</span></code>)</li> <li><a href="couple.html">Solo, Couple, and Merge</a> (<code><span class='Function'>≍></span></code>)</li> diff --git a/docs/doc/match.html b/docs/doc/match.html new file mode 100644 index 00000000..57b239ee --- /dev/null +++ b/docs/doc/match.html @@ -0,0 +1,93 @@ +<head> + <link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/> + <link href="../style.css" rel="stylesheet"/> + <title>BQN: Match</title> +</head> +<div class="nav"><a href="https://github.com/mlochbaum/BQN">BQN</a> / <a href="../index.html">main</a> / <a href="index.html">doc</a></div> +<h1 id="match">Match</h1> +<p>The primitive Match (<code><span class='Function'>≡</span></code>) tests whether its two argument arrays are considered equivalent in BQN, returning <code><span class='Number'>1</span></code> if so and <code><span class='Number'>0</span></code> otherwise. Not Match (<code><span class='Function'>≢</span></code>) is the opposite, returning <code><span class='Number'>1</span></code> if the two arrays aren't equivalent and <code><span class='Number'>0</span></code> if they are.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImFiYyIg4omhICdhJ+KAvydiJ+KAvydjJwo0IOKJoiA8NA==">↗️</a><pre> <span class='String'>"abc"</span> <span class='Function'>≡</span> <span class='String'>'a'</span><span class='Ligature'>‿</span><span class='String'>'b'</span><span class='Ligature'>‿</span><span class='String'>'c'</span> +1 + <span class='Number'>4</span> <span class='Function'>≢</span> <span class='Function'><</span><span class='Number'>4</span> +1 +</pre> +<p>Match always gives the same result as Equals (<code><span class='Function'>=</span></code>) when both arguments are atoms, but the two functions are extended to arrays differently: while Equals maps over array arguments to return an array of results, Match compares them in totality and always returns one boolean (it never gives an error). Match is the basis for BQN's search and self-comparison functions.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImFiYyIgPSAiYWNjIgoiYWJjIiDiiaEgImFjYyIKCiJhYmMiID0gImFiIiAgIyBNaXNtYXRjaGVkIHNoYXBlcwoiYWJjIiDiiaEgImFiIg==">↗️</a><pre> <span class='String'>"abc"</span> <span class='Function'>=</span> <span class='String'>"acc"</span> +⟨ 1 0 1 ⟩ + <span class='String'>"abc"</span> <span class='Function'>≡</span> <span class='String'>"acc"</span> +0 + + <span class='String'>"abc"</span> <span class='Function'>=</span> <span class='String'>"ab"</span> <span class='Comment'># Mismatched shapes +</span>ERROR + <span class='String'>"abc"</span> <span class='Function'>≡</span> <span class='String'>"ab"</span> +0 +</pre> +<p>Match compares arrays based on their fundamental properties—shape and elements—and not the <a href="../spec/inferred.html#fill-elements">fill element</a>, which is an inferred property. Since it can be computed differently in different implementations, using the fill element in Match could lead to some confusing results. Even if the implementation doesn't define a fill for <code><span class='String'>'a'</span><span class='Ligature'>‿</span><span class='String'>'b'</span><span class='Ligature'>‿</span><span class='String'>'c'</span></code>, it should still be considered to match <code><span class='String'>"abc"</span></code>.</p> +<p>To give a precise definition, two arrays are considered to match if they have the same shape and all corresponding elements from the two arrays match. Every array has a finite <a href="depth.html">depth</a> so this recursive definition always ends up comparing non-arrays, or atoms. An array never matches an atom, so the result if only one argument is an atom is <code><span class='Number'>0</span></code>. The interesting case is when both arguments are atoms, discussed below.</p> +<h2 id="atomic-equality">Atomic equality</h2> +<p>Atoms in BQN have five possible <a href="types.html">types</a>: number, character, function, 1-modifier, and 2-modifier. Equality is not allowed to fail for any two arguments, so it needs to be defined on all of these types.</p> +<p>Starting with the easiest rules, values with different types are never equal to each other.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4p+oJ2EnLCArLCAz4p+pID0g4p+oLeKfnMK7LCAnKycsIDPLmeKfqQ==">↗️</a><pre> <span class='Bracket'>⟨</span><span class='String'>'a'</span><span class='Separator'>,</span> <span class='Function'>+</span><span class='Separator'>,</span> <span class='Number'>3</span><span class='Bracket'>⟩</span> <span class='Function'>=</span> <span class='Bracket'>⟨</span><span class='Function'>-</span><span class='Modifier2'>⟜</span><span class='Function'>»</span><span class='Separator'>,</span> <span class='String'>'+'</span><span class='Separator'>,</span> <span class='Number'>3</span><span class='Modifier'>˙</span><span class='Bracket'>⟩</span> +⟨ 0 0 0 ⟩ +</pre> +<p>Two characters are equal when they have the same code point. Numeric equality depends on the number system in use, but probably works about how you expect. If you're coming from APL, note that current BQN implementations don't employ comparison tolerance. To see if two floats are roughly equal you'll need to write a tolerant comparison yourself, but how often do you really need to do this?</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=J3gnID0gInd4eXoiCjEuMjUgPSAxICsgMC4yNQ==">↗️</a><pre> <span class='String'>'x'</span> <span class='Function'>=</span> <span class='String'>"wxyz"</span> +⟨ 0 1 0 0 ⟩ + <span class='Number'>1.25</span> <span class='Function'>=</span> <span class='Number'>1</span> <span class='Function'>+</span> <span class='Number'>0.25</span> +1 +</pre> +<p>Operations are more difficult. Here there are three cases:</p> +<ul> +<li>Primitives are equal if they have the same glyph.</li> +<li>Compound functions or modifiers are split into components.</li> +<li>Block instances are equal if they are the same instance.</li> +</ul> +<p>The first two are fairly similar to how numbers and arrays work. Primitives and compounds like trains, or modifiers with bound operands, are immutable, so they are defined purely by what components they contain.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4p+oKywtLMOX4p+pID0g4p+oKywtLMO34p+pCuKfqCsgLSDDl+KfqSA9IOKfqCsgLSDDt+KfqSAgIyBDb21wYXJlIHR3byB0aHJlZS10cmFpbnMgY29tcG9uZW50LXdpc2UK4p+oKyAtIMO34p+pID0g4p+oKyAtIMO34p+p">↗️</a><pre> <span class='Bracket'>⟨</span><span class='Function'>+</span><span class='Separator'>,</span><span class='Function'>-</span><span class='Separator'>,</span><span class='Function'>×</span><span class='Bracket'>⟩</span> <span class='Function'>=</span> <span class='Bracket'>⟨</span><span class='Function'>+</span><span class='Separator'>,</span><span class='Function'>-</span><span class='Separator'>,</span><span class='Function'>÷</span><span class='Bracket'>⟩</span> +⟨ 1 1 0 ⟩ + <span class='Bracket'>⟨</span><span class='Function'>+</span> <span class='Function'>-</span> <span class='Function'>×</span><span class='Bracket'>⟩</span> <span class='Function'>=</span> <span class='Bracket'>⟨</span><span class='Function'>+</span> <span class='Function'>-</span> <span class='Function'>÷</span><span class='Bracket'>⟩</span> <span class='Comment'># Compare two three-trains component-wise +</span>⟨ 0 ⟩ + <span class='Bracket'>⟨</span><span class='Function'>+</span> <span class='Function'>-</span> <span class='Function'>÷</span><span class='Bracket'>⟩</span> <span class='Function'>=</span> <span class='Bracket'>⟨</span><span class='Function'>+</span> <span class='Function'>-</span> <span class='Function'>÷</span><span class='Bracket'>⟩</span> +⟨ 1 ⟩ +</pre> +<p>This approach can't tell you whether two functions are mathematically different—that is, whether they ever return different results given the same arguments (this is an undecidable problem, and also gets confusing since "different" is included in its own definition). However, if two functions compare equal, then they will always return the same results.</p> +<h3 id="block-equality">Block equality</h3> +<p>The final point above about block instances is subtler. An instance of a block function or modifier is mutable, meaning that its behavior can change over the course of a program. Consider the following two functions:</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RuKAv0cg4oaQIHsgYeKGkDEwIOKLhCB7YSvwnZWpfeKAv3th4oap8J2VqX0gfQpGIDUgICAjIE9uZSByZXN1bHQKRyA4CkYgNSAgICMgQW5vdGhlciByZXN1bHTigJR0aGUgZGVmaW5pdGlvbiBvZiBpbnNhbml0eSE=">↗️</a><pre> <span class='Function'>F</span><span class='Ligature'>‿</span><span class='Function'>G</span> <span class='Gets'>←</span> <span class='Brace'>{</span> <span class='Value'>a</span><span class='Gets'>←</span><span class='Number'>10</span> <span class='Separator'>⋄</span> <span class='Brace'>{</span><span class='Value'>a</span><span class='Function'>+</span><span class='Value'>𝕩</span><span class='Brace'>}</span><span class='Ligature'>‿</span><span class='Brace'>{</span><span class='Value'>a</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Brace'>}</span> <span class='Brace'>}</span> +⟨ *function* *function* ⟩ + <span class='Function'>F</span> <span class='Number'>5</span> <span class='Comment'># One result +</span>15 + <span class='Function'>G</span> <span class='Number'>8</span> +8 + <span class='Function'>F</span> <span class='Number'>5</span> <span class='Comment'># Another result—the definition of insanity! +</span>13 +</pre> +<p>(A side note is that BQN restricts what can cause these side effects: they can only happen by calling a block function or modifier, and never a primitive or purely tacit operation). Now suppose we share the value of <code><span class='Function'>F</span></code> with another variable. When we apply <code><span class='Function'>G</span></code>, the result of <code><span class='Function'>F</span></code> might change, but so does <code><span class='Function'>F1</span></code>! This effect is called <a href="https://en.wikipedia.org/wiki/Aliasing_(computing)">aliasing</a>.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RjEg4oaQIEYKe/CdlY8gNn3CqCBG4oC/RjEKRyAzCnvwnZWPIDZ9wqggRuKAv0Yx">↗️</a><pre> <span class='Function'>F1</span> <span class='Gets'>←</span> <span class='Function'>F</span> + <span class='Brace'>{</span><span class='Function'>𝕏</span> <span class='Number'>6</span><span class='Brace'>}</span><span class='Modifier'>¨</span> <span class='Function'>F</span><span class='Ligature'>‿</span><span class='Function'>F1</span> +⟨ 14 14 ⟩ + <span class='Function'>G</span> <span class='Number'>3</span> +3 + <span class='Brace'>{</span><span class='Function'>𝕏</span> <span class='Number'>6</span><span class='Brace'>}</span><span class='Modifier'>¨</span> <span class='Function'>F</span><span class='Ligature'>‿</span><span class='Function'>F1</span> +⟨ 9 9 ⟩ +</pre> +<p>In some cases you might not be able to demonstrate aliasing so cleanly. A function such as a random number generator changes its own state, so calling one function will change the other. Comparison tells you whether two blocks are the same.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ZiA9IGYx">↗️</a><pre> <span class='Value'>f</span> <span class='Function'>=</span> <span class='Value'>f1</span> +1 +</pre> +<p>As with other kinds of functions, just because two blocks always behave the same doesn't mean they are equal. Any function that's written as <code><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code> will always work the same as other functions spelled that way, but the two functions below are different instances because they come from two different places in the source code.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=PcK0IHvwnZWpfeKAv3vwnZWpfQ==">↗️</a><pre> <span class='Function'>=</span><span class='Modifier'>´</span> <span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Brace'>}</span><span class='Ligature'>‿</span><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Brace'>}</span> +0 +</pre> +<p>Two blocks that come from the same source code location could also be different. Consider the following code, featuring a function that creates block functions:</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=R2VuIOKGkCB7IGHihpDwnZWpIOKLhCB7YcOX8J2VqX0gfQp0MiDihpAgR2VuIDIKdDMg4oaQIEdlbiAzCnvwnZWPIDR9wqggVDLigL9UMw==">↗️</a><pre> <span class='Function'>Gen</span> <span class='Gets'>←</span> <span class='Brace'>{</span> <span class='Value'>a</span><span class='Gets'>←</span><span class='Value'>𝕩</span> <span class='Separator'>⋄</span> <span class='Brace'>{</span><span class='Value'>a</span><span class='Function'>×</span><span class='Value'>𝕩</span><span class='Brace'>}</span> <span class='Brace'>}</span> + <span class='Value'>t2</span> <span class='Gets'>←</span> <span class='Function'>Gen</span> <span class='Number'>2</span> + <span class='Value'>t3</span> <span class='Gets'>←</span> <span class='Function'>Gen</span> <span class='Number'>3</span> + <span class='Brace'>{</span><span class='Function'>𝕏</span> <span class='Number'>4</span><span class='Brace'>}</span><span class='Modifier'>¨</span> <span class='Function'>T2</span><span class='Ligature'>‿</span><span class='Function'>T3</span> +⟨ 8 12 ⟩ +</pre> +<p>These functions both have the definition <code><span class='Brace'>{</span><span class='Value'>a</span><span class='Function'>×</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>, but give different results! They are different <em>instances</em> of the same block, and have different environments: for <code><span class='Function'>T2</span></code>, <code><span class='Value'>a</span></code> is <code><span class='Number'>2</span></code>, and for <code><span class='Function'>T3</span></code>, it's <code><span class='Number'>3</span></code>.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=dDIgPSB0Mw==">↗️</a><pre> <span class='Value'>t2</span> <span class='Function'>=</span> <span class='Value'>t3</span> +0 +</pre> +<p>Some definitions should help to make things clearer. A "block" is not actually a BQN value, but a region of source code enclosed in <code><span class='Brace'>{}</span></code> brackets. When the program encounters a block function or modifier, it creates an instance of this block, and then uses this instance in the rest of the expression (actually, an immediate block also creates an instance, but this instance is immediately run, and discarded when it finishes, so it can't be accessed as a value). Every time the function <code><span class='Function'>Gen</span></code> is run, it evaluates the statements it contains, and the second statement <code><span class='Brace'>{</span><span class='Value'>a</span><span class='Function'>×</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code> creates a block instance. So <code><span class='Function'>Gen</span></code> creates a new block instance each time. This is necessary for <code><span class='Function'>Gen</span></code> to work correctly: each time it runs, it creates a new scope, so it needs to create a new function that will be tied to that scope.</p> diff --git a/docs/doc/primitive.html b/docs/doc/primitive.html index b1ba12c5..a77ae4e6 100644 --- a/docs/doc/primitive.html +++ b/docs/doc/primitive.html @@ -110,12 +110,12 @@ <tr> <td><code><span class='Function'>≡</span></code></td> <td><a href="depth.html">Depth</a>*</td> -<td><a href="https://aplwiki.com/wiki/Match">Match</a></td> +<td><a href="match.html">Match</a></td> </tr> <tr> <td><code><span class='Function'>≢</span></code></td> <td><a href="https://aplwiki.com/wiki/Shape">Shape</a></td> -<td><a href="https://aplwiki.com/wiki/Not_Match">Not Match</a></td> +<td><a href="match.html">Not Match</a></td> </tr> <tr> <td><code><span class='Function'>⊣</span></code></td> |
