Idioms, Gates, and Design Patterns#
When one has spent enough time working with Nock, patterns emerge. While it’s unrealistic to simply sit and read a Nock program at a glance, it is very possible to recognize macroscopic structures that recur.
Gates#
Opcode 9 is built to recall a stored procedure, modify it in a characteristic way, and then invoke it. This pattern, called a “gate”, occurs frequently in Nock programs as the most convenient way to implement a function or a subroutine.
Because the gate is intended to be reused, it is stored with an opcode 1 so it can be retrieved and manipulated as a constant noun prior to execution.
For instance, this Nock program makes a gate that returns its argument incremented by 1:
[8 [1 0] [1 4 0 6] 0 1]
One way to invoke it with an opcode 9 looks like this:
[7
[8 [1 0] [1 4 0 6] 0 1]
[8 [0 1]
[9 2
10 [6 7 [0 3] 1 5] 0 2]]
]
The meat of the pattern lies in the opcode 9 expression, which we may gloss as follows:
Retrieve the gate
We can expand it using the rules for opcodes 7, 8, and 9 (using 0
as an unused placeholder subject):
*[a 7 b c] *[*[a b] c]
*[a 8 b c] *[[*[a b] a] c]
*[a 9 b c] *[*[a c] 2 [0 1] 0 b]
*[0 7 [8 [1 0] [1 4 0 6] 0 1] [8 [0 1] [9 2 10 [6 7 [0 3] 1 5] 0 2]]] ==
*[*[0 [8 [1 0] [1 4 0 6] 0 1]] [8 [0 1] [9 2 10 [6 7 [0 3] 1 5] 0 2]]] ==
TODO
*[8 [0 1] 9 2 10 [6 7 [0 3] 1 5] 0 2] ==
*[*[a 10 [6 7 [0 3] 1 5] 0 2] 2 [0 1] 0 2]
Cores#
A gate is a specific instance of a more general pattern called a “core”. The purpose of a core is to collect a battery of code (even one gate) intended for reuse. Compare this code, which features two opcode 8 pins, to the prior increment gate:
[8 [1 8 [1 0]
[1 4 0 6] 0 1]
[8 [9 2 0 1] 9 2 10 [6 7 [0 3] 1 5] 0 2]]
Its standard invocation uses opcode 9 twice: once to retrieve the core, and once to invoke the target gate.
We can in fact distinguish two ways of storing data in a core: as code, using opcode 8 pins, and as data, using opcode 1 pins. This one, for instance, stores the number 42 as raw data inside the core:
[8 [1 [1 42] 8 [1 0] [1 4 0 6] 0 1] 8 [9 5 0 1] 9 2 10 [6 7 [0 3] 1 5] 0 2]
A core is a noun of the form [battery payload]
, where the battery is a noun that can be used to compute new cores, and the payload is an arbitrary noun. (It is worth reiterating at this point that Nock has no preference for this structure; it is simply a convention that Nock programmers use to organize their code.)
Gate-Building Gates#
Besides