From 0c716e4c6b7c2c44bbfd02b6503cae66af7b7480 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Fri, 28 Jan 2022 16:34:41 -0500 Subject: Separate syntax highlighting category for header/body characters ;:? --- docs/doc/embed.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'docs/doc/embed.html') diff --git a/docs/doc/embed.html b/docs/doc/embed.html index bdd03679..b02342cc 100644 --- a/docs/doc/embed.html +++ b/docs/doc/embed.html @@ -9,16 +9,16 @@

There is only one mechanism to interface between the host language and BQN: the function bqn 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!

Passing closures

Probably you can figure out the easy things like calling bqn("×´1+↕6") to compute six factorial. But how do you get JS and BQN to talk to each other, for example to compute the factorial of a number n? Constructing a source string with bqn("×´1+↕"+n) isn't the best way—in fact I would recommend you never use this strategy.

-

Instead, return a function from BQN and call it: bqn("{×´1+↕𝕩}")(n). This strategy also has the advantage that you can store the function, so that it will only be compiled once. Define let fact = bqn("{×´1+↕𝕩}"); at the top of your program and use it as a function elsewhere.

+

Instead, return a function from BQN and call it: bqn("{×´1+↕𝕩}")(n). This strategy also has the advantage that you can store the function, so that it will only be compiled once. Define let fact = bqn("{×´1+↕𝕩}"); at the top of your program and use it as a function elsewhere.

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, bqn("{𝕏'a'+↕26}")(alert) calls the argument alert 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.

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 i and then returns a function that manipulates i and returns its new value.

let push = bqn(`
     i40
     {i+𝕩»i}
-`);
-push(3);    // [3,0,0,0]
-push(-2);   // [1,3,0,0]
-push(4);    // [5,4,3,0]
+`);
+push(3);    // [3,0,0,0]
+push(-2);   // [1,3,0,0]
+push(4);    // [5,4,3,0]
 

Note that this program doesn't have any outer braces. It's only run once, and it initializes i 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 𝕨 or 𝕩 inside them would turn it into a function that could be run multiple times to create different closures. For example, pushGen = bqn("{i←4⥊𝕩⋄{i+↩𝕩»i}}") causes pushGen(n) to create a new closure with i initialized to 4n.

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.

@@ -28,7 +28,7 @@ RotY {a𝕩a} Flip {𝕤aa} RotXRotYFlip -`); +`);

When defining closures for their side effects like this, make sure they are actually functions! For example, since flip ignores its argument (you can call it with flip(), because a right argument of undefined isn't valid but will just be ignored), it needs an extra 𝕤 in the definition to be a function instead of an immediate block.

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 list() converts a JS array into a BQN list by using its length for the shape; the next section has a few more details.

-- cgit v1.2.3