1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
<head>
<link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
<link href="../style.css" rel="stylesheet"/>
<title>Using embedded BQN</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="using-embedded-bqn">Using embedded BQN</h1>
<p>The Javascript implementation of BQN, <a href="https://github.com/mlochbaum/BQN/blob/master/doc/../docs/bqn.js">docs/bqn.js</a>, can be <a href="https://mlochbaum.github.io/BQN/try.html">used</a> as a standalone interpreter, but it can also be called from JS, which in combination with BQN's first-class functions allows the two language to interoperate well. Similar functionality will most likely be brought to other host languages in the future. Languages that (like JS) allow functions and arrays to be tagged with extra properties can host a full BQN implementation with good interoperability. Other languages would either require functions and arrays to be stored in specialized data structures, making interoperability a little harder, or would miss out on some inferred properties like function inverses and array fills.</p>
<p>There is only one mechanism to interface between the host language and BQN: the function <code><span class='Value'>bqn</span></code> evaluates a string containing a BQN program and returns the result. Doesn't sound like much, especially considering these programs can't share any state such as global variables (BQN doesn't have those). But taking first-class functions and closures into account, it's all you could ever need!</p>
<h2 id="passing-closures">Passing closures</h2>
<p>Probably you can figure out the easy things like calling <code><span class='Value'>bqn</span><span class='Paren'>(</span><span class='String'>"×´1+↕6"</span><span class='Paren'>)</span></code> to compute six factorial. But how do you get JS and BQN to <em>talk</em> to each other, for example to compute the factorial of a number <code><span class='Value'>n</span></code>? Constructing a source string with <code><span class='Value'>bqn</span><span class='Paren'>(</span><span class='String'>"×´1+↕"</span><span class='Function'>+</span><span class='Value'>n</span><span class='Paren'>)</span></code> isn't the best way—in fact I would recommend you never use this strategy.</p>
<p>Instead, return a function from BQN and call it: <code><span class='Value'>bqn</span><span class='Paren'>(</span><span class='String'>"{×´1+↕𝕩}"</span><span class='Paren'>)(</span><span class='Value'>n</span><span class='Paren'>)</span></code>. This strategy also has the advantage that you can store the function, so that it will only be compiled once. Define <code><span class='Value'>let</span> <span class='Value'>fact</span> <span class='Function'>=</span> <span class='Value'>bqn</span><span class='Paren'>(</span><span class='String'>"{×´1+↕𝕩}"</span><span class='Paren'>)</span><span class='Value'>;</span></code> at the top of your program and use it as a function elsewhere.</p>
<p>BQN can also call JS functions, to use functionality that isn't native to BQN or interact with a program written in JS. For example, <code><span class='Value'>bqn</span><span class='Paren'>(</span><span class='String'>"{𝕏'a'+↕26}"</span><span class='Paren'>)(</span><span class='Value'>alert</span><span class='Paren'>)</span></code> calls the argument <code><span class='Value'>alert</span></code> from within BQN. The displayed output isn't quite right here, because a BQN string is stored as a JS array, not a string. See the next section for more information.</p>
<p>Cool, but none of these examples really use closures, just self-contained functions. Closures are functions that use outside state, which is maintained over the course of the program. Here's an example program that defines <code><span class='Value'>i</span></code> and then returns a function that manipulates <code><span class='Value'>i</span></code> and returns its new value.</p>
<pre><span class='Value'>let</span> <span class='Value'>push</span> <span class='Function'>=</span> <span class='Value'>bqn</span><span class='Paren'>(</span><span class='Modifier'>`</span>
<span class='Value'>i</span><span class='Gets'>←</span><span class='Number'>4</span><span class='Function'>⥊</span><span class='Number'>0</span>
<span class='Brace'>{</span><span class='Value'>i</span><span class='Function'>+</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Function'>»</span><span class='Value'>i</span><span class='Brace'>}</span>
<span class='Modifier'>`</span><span class='Paren'>)</span><span class='Value'>;</span>
<span class='Value'>push</span><span class='Paren'>(</span><span class='Number'>3</span><span class='Paren'>)</span><span class='Value'>;</span> <span class='Function'>//</span> <span class='Value'>[</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Value'>]</span>
<span class='Value'>push</span><span class='Paren'>(</span><span class='Function'>-</span><span class='Number'>2</span><span class='Paren'>)</span><span class='Value'>;</span> <span class='Function'>//</span> <span class='Value'>[</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Value'>]</span>
<span class='Value'>push</span><span class='Paren'>(</span><span class='Number'>4</span><span class='Paren'>)</span><span class='Value'>;</span> <span class='Function'>//</span> <span class='Value'>[</span><span class='Number'>5</span><span class='Separator'>,</span><span class='Number'>4</span><span class='Separator'>,</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Value'>]</span>
</pre>
<p>Note that this program doesn't have any outer braces. It's only run once, and it initializes <code><span class='Value'>i</span></code> and returns a function. Just putting braces around it wouldn't have any effect—it just changes it from a program that does something to a program that runs a block that does the same thing—but adding braces and using <code><span class='Value'>𝕨</span></code> or <code><span class='Value'>𝕩</span></code> inside them would turn it into a function that could be run multiple times to create different closures. For example, <code><span class='Value'>pushGen</span> <span class='Function'>=</span> <span class='Value'>bqn</span><span class='Paren'>(</span><span class='String'>"{i←4⥊𝕩⋄{i+↩𝕩»i}}"</span><span class='Paren'>)</span></code> causes <code><span class='Value'>pushGen</span><span class='Paren'>(</span><span class='Value'>n</span><span class='Paren'>)</span></code> to create a new closure with <code><span class='Value'>i</span></code> initialized to <code><span class='Number'>4</span><span class='Function'>⥊</span><span class='Value'>n</span></code>.</p>
<p>The program also returns only one function, which can be limiting. But it's possible to get multiple closures out of the same program by returning a list of functions. For example, the following program defines three functions that manipulate a shared array in different ways.</p>
<pre><span class='Value'>let</span> <span class='Value'>[rotx</span><span class='Separator'>,</span> <span class='Value'>roty</span><span class='Separator'>,</span> <span class='Value'>flip]</span> <span class='Function'>=</span> <span class='Value'>bqn</span><span class='Paren'>(</span><span class='Modifier'>`</span>
<span class='Value'>a</span> <span class='Gets'>←</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='Function'>RotX</span> <span class='Gets'>←</span> <span class='Brace'>{</span><span class='Value'>a</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Function'>⌽</span><span class='Modifier'>˘</span><span class='Value'>a</span><span class='Brace'>}</span>
<span class='Function'>RotY</span> <span class='Gets'>←</span> <span class='Brace'>{</span><span class='Value'>a</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Function'>⌽</span><span class='Value'>a</span><span class='Brace'>}</span>
<span class='Function'>Flip</span> <span class='Gets'>←</span> <span class='Brace'>{</span><span class='Value'>𝕤</span><span class='Separator'>⋄</span><span class='Value'>a</span><span class='Gets'>↩</span><span class='Function'>⍉</span><span class='Value'>a</span><span class='Brace'>}</span>
<span class='Function'>RotX</span><span class='Ligature'>‿</span><span class='Function'>RotY</span><span class='Ligature'>‿</span><span class='Function'>Flip</span>
<span class='Modifier'>`</span><span class='Paren'>)</span><span class='Value'>;</span>
</pre>
<p>When defining closures for their side effects like this, make sure they are actually functions! For example, since <code><span class='Value'>flip</span></code> ignores its argument (you can call it with <code><span class='Value'>flip</span><span class='Paren'>()</span></code>, because a right argument of <code><span class='Value'>undefined</span></code> isn't valid but will just be ignored), it needs an extra <code><span class='Value'>𝕤</span></code> in the definition to be a function instead of an immediate block.</p>
<p>You can also use an array to pass multiple functions or other values from JS into BQN all at once. However, a JS array can't be used directly in BQN because its shape isn't known. The function <code><span class='Value'>list</span><span class='Paren'>()</span></code> converts a JS array into a BQN list by using its length for the shape; the next section has a few more details.</p>
<h2 id="js-encodings">JS encodings</h2>
<p>In the programs above we've used numbers and functions of one argument, which mean the same thing in BQN and JS. This isn't the case for all types: although every BQN value is stored as some JS value, the way it's represented may not be obvious and there are many JS values that don't represent any BQN value and could cause errors. BQN operations don't verify that their inputs are valid BQN values (this would have a large performance cost), so it's up to the JS programmer to make sure that values passed in are valid. To do this, you need to know the encodings for each of the seven BQN <a href="types.html">types</a> you're going to use.</p>
<p>The two atomic data values are simple: numbers are just JS numbers, and characters are strings containing a single code point. Arrays <em>are</em> JS arrays, but with some extra information. Since JS arrays are 1-dimensional, a BQN array <code><span class='Value'>a</span></code> is stored as the element list <code><span class='Function'>⥊</span><span class='Value'>a</span></code>. Its shape <code><span class='Function'>≢</span><span class='Value'>a</span></code>, a list of numbers, is <code><span class='Value'>a.sh</span></code> in JS (the shape isn't necessarily a BQN array so it doesn't have to have a <code><span class='Value'>sh</span></code> property). Optionally, its fill element is <code><span class='Value'>a.fill</span></code>. Note that a BQN string is not a JS string, but instead an array of BQN characters, or JS strings. To convert it to a JS string you can use <code><span class='Value'>str.join</span><span class='Paren'>(</span><span class='String'>""</span><span class='Paren'>)</span></code>.</p>
<p>There are two utilities for converting from JS to BQN data: <code><span class='Value'>list</span><span class='Paren'>(</span><span class='Value'>[…]</span><span class='Paren'>)</span></code> converts a JS array to a BQN list, and <code><span class='Value'>str</span><span class='Paren'>(</span><span class='String'>"JS string"</span><span class='Paren'>)</span></code> converts a string.</p>
<p>Operations are all stored as JS functions, with one or two arguments for the inputs. The type is determined by the <code><span class='Value'>.m</span></code> property, which is <code><span class='Number'>1</span></code> for a 1-modifier and <code><span class='Number'>2</span></code> for a 2-modifier, and undefined or falsy for a function. Functions might be called with one or two arguments. In either case, <code><span class='Value'>𝕩</span></code> is the first argument; <code><span class='Value'>𝕨</span></code>, if present, is the second. Note that <code><span class='Function'>F</span><span class='Paren'>(</span><span class='Value'>x</span><span class='Separator'>,</span><span class='Value'>w</span><span class='Paren'>)</span></code> in JS corresponds to <code><span class='Value'>w</span> <span class='Function'>F</span> <span class='Value'>x</span></code> in BQN, reversing the visual ordering of the arguments! For modifiers there's no such reversal, as <code><span class='Value'>𝕗</span></code> is always the first argument, and for 2-modifiers <code><span class='Value'>𝕘</span></code> is the second argument. As in BQN, a modifier may or may not return a function.</p>
<p>Operations may have some extra properties set that aren't terribly important for the JS programmer: for each primitive <code><span class='Value'>p</span></code>, <code><span class='Value'>p.glyph</span></code> gives its glyph, and for a compound operation <code><span class='Value'>o</span></code> such as a train, or a modifier with bound operands, <code><span class='Value'>o.repr</span><span class='Paren'>()</span></code> decomposes it into its parts. It wouldn't make sense to define either of these properties for a function created in JS.</p>
<h2 id="other-functionality">Other functionality</h2>
<p>The BQN script also contains the function <code><span class='Value'>fmt</span></code>, which takes a BQN value for its argument and returns a string displaying it.</p>
<p>The expression diagram builder used for the REPL's "Explain" button isn't included in the main BQN script: it's kept in <a href="https://github.com/mlochbaum/BQN/blob/master/doc/../docs/repl.js">docs/repl.js</a> instead. It's a little tricky to use as it takes both the source string and the bytecode obtained from compiling the source: see the surrounding Javascript code for an example. The result is the source code for an svg, as a BQN string.</p>
|