•ReBQN
The official documentation describes it well, though more information about its 𝕩 namespace is provided by the spec. But, it's easy to gloss over what's read. I've also had people gloss over my words when discussing •ReBQN: "oh, it's just eval()" or "oh, it's just a way to add new primitives". What •ReBQN does is create interpreters for BQN-like languages - with custom primitives and system values, and optional state.
So you can use it as eval() with a controlled environment. Or you can write all of your Advent of Code submissions in a very slightly modified dialect of BQN that has an A* primitive. Or you can experiment with your own APL with your own hieroglyphics, as long as it shares BQN's grammar.
There are some subtle points:
- You can use any Unicode character but you can't break the grammar: so, т е с т Cyrillic characters can all be primitives, but тест can't be a single primitive, and t e s t Latin characters can't be primitives as variables use those characters.
- It doesn't trap exceptions in evaluated code.
- System values and primitives are controlled separately:
calcFns ← ⟨'+'‿+, '-'‿-, '*'‿×, '/'‿(↕⊘÷)⟩ ⟨ ⟨ '+' + ⟩ ⟨ '-' - ⟩ ⟨ '*' × ⟩ ⟨ '/' ↕⊘÷ ⟩ ⟩ calc ← •ReBQN {primitives⇐calcFns} (REPL) Calc "•SH ""echo""‿""still works""" ⟨ 0 "still works " ⟨⟩ ⟩ calc ↩ •ReBQN {primitives⇐calcFns, system⇐⟨⟩} (REPL) Calc "•SH ""echo""‿""no more""" Error: Unknown system function •sh at Calc "•SH ""echo""‿""no more""" ^^^^ - Although primitives can't be subjects, system values can be:
# create a BQN-plus-•words dialect words ← •ReBQN {system⇐•listSys∾⟨"words"‿(•file.Lines "/usr/share/dict/words")⟩} (REPL) Words "≠ •words" 479826 - Getting values from the interpreter is easy, because every call to the interpreter returns a value. Getting values into the interpreter is not so simple as the
scopeoption isn't implemented. Custom primitives or system values can still do it:queue ← 1‿4‿3 ⟨ 1 4 3 ⟩ calc ↩ •ReBQN {system⇐•listSys∾⟨"next"‿{𝕊: x←⊑queue ⋄ queue 1⊸↓ ↩ ⋄ x}⟩} (REPL) {𝕊:Calc"•Next@"}¨↕3 ⟨ 1 4 3 ⟩ queue ↩ 5‿6 ⟨ 5 6 ⟩ {𝕊:Calc"•Next@"}¨↕2 ⟨ 5 6 ⟩