{"id":13638934,"url":"https://github.com/niblyx-malnus/Nock10Tutorial","last_synced_at":"2025-04-19T21:35:09.345Z","repository":{"id":143317562,"uuid":"420707571","full_name":"niblyx-malnus/Nock10Tutorial","owner":"niblyx-malnus","description":"Derive Nock 10 from Nocks 0 through 5","archived":false,"fork":false,"pushed_at":"2022-03-19T17:18:40.000Z","size":157,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-09T09:37:57.402Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/niblyx-malnus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-10-24T14:29:40.000Z","updated_at":"2024-02-23T02:26:17.000Z","dependencies_parsed_at":"2023-05-13T16:30:44.416Z","dependency_job_id":null,"html_url":"https://github.com/niblyx-malnus/Nock10Tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niblyx-malnus%2FNock10Tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niblyx-malnus%2FNock10Tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niblyx-malnus%2FNock10Tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niblyx-malnus%2FNock10Tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/niblyx-malnus","download_url":"https://codeload.github.com/niblyx-malnus/Nock10Tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249811138,"owners_count":21328749,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T01:00:55.561Z","updated_at":"2025-04-19T21:35:09.129Z","avatar_url":"https://github.com/niblyx-malnus.png","language":null,"funding_links":[],"categories":["Educational Resources"],"sub_categories":["SAIL"],"readme":"# Deriving Nocks 6 through 11 \n_In order for the following to make sense to you, you should be fairly familiar with the basics of Nock. Also, I use == and := as equality and assignment operators respectively; not to be confused with Hoon runes or terminators._\n\n## Motivation\nIt is a fun exercise when learning Nock to try to derive Nocks 6 through 11 with Nocks 0 through 5. We know (or suspect) that this is possible since Nocks 0 through 5 are billed as a Turing-complete ruleset. In fact, Nocks 6 through 9 and Nock 11 are quite trivial (of these, Nock 6 is the most involved) since they are defined in terms of the `*` tar expression evaluator and Nocks 0 through 5. It is still instructive to write these entirely as nouns which can be evaluated against some subject using the Hoon `.*` dottar rune. (In the following, take `*[a ^]` to be the same as `.*(a ^)`.)\n\nNock 10 is not expressed in this way, however. It is expressed in terms of the `#` hax edit operator:\n\n`*[a 10 [b c] d] ==  #[b *[a c] *[a d]]`\n\nI have heard it [speculated](https://www.youtube.com/watch?app=desktop\u0026t=25m53s\u0026v=H4EHy-DfiGY\u0026feature=youtu.be%3Ft%3D25m53s)\u003csup\u003e1\u003c/sup\u003e that Nock 10 cannot be expressed using Nocks 0 through 5. I myself have entertained this thought. However, this is impossible! Nocks 0 through 5 are Turing-complete! We must be able to construct Nock 10 with these rules alone. In fact, we have a hint as to how to do so in the definition of the `#` hax edit operator:\n\n`#[1 a b] ============ a`  \n`#[(a + a) b c] ====== #[a [b /[(a + a + 1) c]] c]`  \n`#[(a + a + 1) b c] == #[a [/[(a + a) c] b] c]`  \n\nThat's right! We have the `#` hax edit operator recursively defined in terms of our `/` fas slot operator, whose effect we can reproduce with real Nock code using Nock 0. As long as we have a way to keep track of whether `a` is odd or even, we should be able to write this code in simple Nock. We will use this insight to create our own Nock 10 from scratch. \n\nThis process will be easier using Nocks 6, 7, 8, and 9, however. So let us convince ourselves that these can be expressed as nouns composed of only Nocks 0 through 5.\n\n## Nock 7\nWe  will start with Nock 7 because it is the easiest:\n\n`*[a 7 b c] == *[*[a b] c]`\n\nThis looks a lot like Nock 2:\n\n`*[a 2 b c] == *[*[a b] *[a c]]`\n\nIn fact, this basically is just a glorified Nock 2, which allows for more direct function composition. We can easily see that if we replace our `c` from Nock 2 with a `[1 c]` we get:\n\n`*[a 2 b 1 c] == *[*[a b] *[a 1 c]] == *[*[a b] c]`\n\nTherefore `*[a 7 b c]` and `*[a 2 b 1 c]` are equivalent.\n\n### Nock 7 Primitive Equivalent\n`*[a 7 b c] == *[a 2 b 1 c]`\n\n## Nock 8\nNock 8 is also fairly straightforward. \n\n`*[a 8 b c] == *[[*[a b] a] c]`\n\nThis extends the noun by pinning another noun `*[a b]` to its head, and then runs a formula `c` on this new noun. We notice two things here. One is function composition. First we add a noun to the head. Then we apply a formula to the new noun. This suggests Nock 7 and thus Nock 2. We also notice the creation of a cell from two nouns.\n\nRecall the rule:\n\n`*[a [b c] d] == [*[a b c] *[a d]]`\n\n`[*[a b] a]` can be rewritten `[*[a b] *[a 0 1]]` which can be rewritten as\n`*[a b 0 1]`. \n\nBy substituting back into our original formula we get:\n\n`*[[*[a b] a] c] == *[*[a b 0 1] c] == *[a 7 [b 0 1] c] == *[a 2 [b 0 1] 1 c]`\n\n### Nock 8 Primitive Equivalent\n`*[a 8 b c] == *[a 2 [b 0 1] 1 c]`\n\n## Nock 9\nNock 9 is the \"function invocation\" opcode. It performs some function `c` on the subject `a` and then extracts the function at slot `b` from this new subject and runs that function against that same new subject.\n\n`*[a 9 b c] == *[*[a c] 2 [0 1] 0 b]`\n\nMuch of the work here is already done for us. We have a formula `[2 [0 1] 0 b]` being applied to the result of a formula `c` being applied to subject `a`. This is just Nock 7 `*[a 7 c 2 [0 1] 0 b]` which is just Nock 2\n`*[a 2 c 1 2 [0 1] 0 b]`.\n\n### Nock 9 Primitive Equivalent\n`*[a 9 b c] == *[a 2 c 1 2 [0 1] 0 b]`\n\nAs an aside, we can note that the Nock 9 is defined in terms of a combination of pseudocode operators and Nock opcodes. We can also go the other way to see what Nock 9 looks like in pure pseudocode operators.\n\n```\n*[a 9 b c]\n== *[*[a c] 2 [0 1] 0 b]\n== *[*[*[a c] 0 1] *[*[a c] 0 b]]\n== *[*[a c] /[b *[a c]]]\n```\n\n### Nock 9 Pseudocode Operator Equivalent\n```\n*[a 9 b c] == *[*[a c] /[b *[a c]]]\n```\n\n## Nock 6\n### Explaining Nock 6\nOkay. Of all the opcodes so far, Nock 6 is the most complex. It is the if-then-else operator in Nock. It takes a function `b` which computes a loobean `*[a b]` on subject `a` and returns `*[a c]` if the loobean is yes (`0`) and `*[a d]` if the loobean is no (`1`).\n\n`*[a 6 b c d] == *[a *[[c d] 0 *[[2 3] 0 *[a 4 4 b]]]]`\n\nInstead of working backwards from this formula, let's derive it ourselves. First, let's select `c` or `d` from a cell `[c d]` based on whether `*[a b]` is `0` or `1`. If `*[a b]` is `0` we want to slot into the head of `[c d]` at address `2` and if `*[a b]` is `1` we want to slot into the tail of `[c d]` at address `3`. With `*[a 4 4 b] == ++*[a b]` we get address `2` from loobean `0` and address `3` from loobean `1`. To slot into `[c d]` let's simply do `*[[c d] 0 *[a 4 4 b]]`. This gives us either `c` or `d` which we then want to apply to `a`: `*[a *[[c d] 0 *[[a 4 4 b]]]]`. \n\nWe are almost there. But where does the `*[[2 3] 0 *[a 4 4 b]]` come from? Isn't slotting into `[2 3]` with `2` or `3` from `*[a 4 4 b]` redundant? We get the same value back. However, if for some reason `*[a b]` is not a loobean but is still an atom, meaning it is an integer greater than `1` and if `[c d]` is a noun with many nested cells, `*[a 4 4 b]` will return an address greater than `3` which could still be a valid address. `*[[2 3] 0 *[a 4 4 b]]` forces this to return either `2` or `3` or to crash.\n\nThus `*[a *[[c d] 0 *[[2 3] 0 *[a 4 4 b]]]]` or `if *[a b] then *[a c] else *[a d]`.\n\n### Converting Nock 6 to Nocks 0 through 5\nTo convert this to a single noun is straight-forward enough, but it's a bit of a grind. To keep things as clean as possible, like in ~timluc-miptev's [Interlude](https://blog.timlucmiptev.space/faq.html), we will use variables in the dojo. Here is where we start:\n\n`*[a 6 b c d] == *[a *[[c d] 0 *[[2 3] 0 *[a 4 4 b]]]]`\n\n#### Deriving `*[a x] == [0 *[a 4 4 b]]`\nLet's start at the end. In order to construct `[0 *[a 4 4 b]]` on subject `a`, let's notice that it is a cell. When trying to construct a cell with respect to a subject `a` we want to put it in the form `[*[a m] *[a n]]` so that we can recover the original expression `*[a m n]`. The tail of our cell is already in the form `*[a n]`. So how about the head? `*[a 1 0] == 0`. So we can write: \n\n`[0 *[a 4 4 b]] == [*[a 1 0] *[a 4 4 b]] == *[a [1 0] 4 4 b]`\n\nLet's say `=x [[1 0] 4 4 b]`. This gives us:\n\n`[0 *[a 4 4 b]] == *[a x]`\n\nExcellent. We have started to simplify our expression. We now have:\n\n`*[a 6 b c d] == *[a *[[c d] 0 *[[2 3] *[a x]]]]`\n\n#### Deriving `*[a y] == *[2 3] *[a x]]`\nHopefully you see how can we can repeat this process. Let's look at `*[[2 3] *[a x]]`. This has nested expression evaluations. This suggests Nock 2. For Nock 2, we want to get our expression in the form `*[*[a m] *[a n]]` so that we can recover the original expression `*[a 2 m n]`. (This looks like what we did in our first step, but don't be fooled. In the first step we were building a cell. In this step, we are building an expression evaluation.) Notice that `[2 3] == *[a 1 2 3]`. This gives us:\n\n`*[[2 3] *[a x]] == *[*[a 1 2 3] *[a x]] == *[a 2 [1 2 3] x]`\n\nLet's say `=y [2 [1 2 3] x]`. This gives us:\n\n`*[[2 3] *[a x]] == *[a y]`\n\nWe now have:\n\n`*[a 6 b c d] == *[a *[[c d] 0 *[a y]]]`\n\n#### Deriving `*[a z] == [[c d] 0 *[a y]]`\nLet's look at `[0 *[a y]]`. Another cell. We know what to do here.\n\n`[0 *[a y]] == [*[a 1 0] *[a y]] == *[a [1 0] y]`\n\nSo we now have:\n\n`*[a 6 b c d] == *[a *[[c d] *[a [1 0] y]]]`\n\n`*[[c d] *[a [1 0] y]]` has nested expression evaluations. We know what to do here.\n\n`*[[c d] *[a [1 0] y]] == *[*[a 1 c d] *[a [1 0] y]] == *[a 2 [1 c d] [1 0] y]`\n\nThis is starting to get a little verbose again. Let's substitute:\n`=z [2 [1 c d] [1 0] y]`. This gives us:\n\n`*[[c d] 0 *[[2 3] 0 *[a 4 4 b]]] == *[[c d] 0 *[a y]] == *[a z]`\n\nSo now we have:\n\n`*[a 6 b c d] == *[a *[a z]]`\n\nMore nested evaluation expressions.\n\n`*[a *[a z]] == *[*[a 0 1] *[a z]] == *[a 2 [0 1] z]`\n\nFinally, we have:\n\n`*[a 6 b c d] == *[a 2 [0 1] z]`\n\n#### Substituting Back In\nAnd that's the whole expression. Let's substitute back in:\n\n`*[a 2 [0 1] z] == *[a 2 [0 1] 2 [1 c d] [1 0] y]`\n\n`== *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] x]`\n\n`== *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]`\n\nThis is Nock 6 written with only Nock 0 through 5.\n\n### Nock 6 Primitive Equivalent\n`*[a 6 b c d] == *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]`\n\nAs an aside we can notice that Nock 6 (like Nock 9) is defined as a combination of pseudocode operators and Nock opcodes. We can also go the other way to see what Nock 9 looks like in pure pseudocode operators.\n\n```\n*[a 6 b c d]\n== *[a *[[c d] 0 *[[2 3] 0 *[a 4 4 b]]]]\n== *[a *[[c d] 0 *[[2 3] 0 ++*[a b]]]]\n== *[a *[[c d] 0 /[++*[a b] [2 3]]]]\n== *[a /[/[++*[a b] [2 3]] [c d]]]\n```\n\n### Nock 6 Pseudocode Operator Equivalent\n`*[a 6 b c d] == *[a /[/[++*[a b] [2 3]] [c d]]]`\n\nThis is not quite as intuitive as the Nock 9 pseudocode operator equivalent. The definition of Nock 6 is mostly to demonstrate the very cool fact that a branching operation can be derived using only the fundamental operators `*`, `/` and `+`. But we can also look at Nock 6 another way by introducing (in our own mental fork of the Nock spec) a new pseudocode operater `\u003c`.\n\n### Nock 6 New Pseudocode Operator Equivalent\n```\n\u003c[0 a b]          a\n\u003c[1 a b]          b\n\u003ca                \u003ca\n\n*[a 6 b c d]      \u003c[*[a b] *[a c] *[a d]]\n```\n\nThis is equivalent to the original definition. Like `#`, this pseudocode operator is not required for Turing completeness. `*`, `?`, `+`, `=`, and `/` are enough for this. \n\n## Nock 11\n\nEven though we don't need Nock 11 to build Nock 10, for the sake of our collective OCD, let's note that Nock 11 can also trivially be written as a noun. The definition of Nock 11 is:\n\n`*[a 11 [b c] d] == *[[*[a c] *[a d]] 0 3]`  \n`*[a 11 b c] ====== *[a c]`  \n\nThe hint provided by this code is used in the process of jetting. In the first case, an atomic tag `b` is provided and a formula `c` is used to compute additional hint information on the subject. `d` is the formula we are actually trying to compute. In the second case, only the atomic tag `b` is passed and `c` is the formula we are actually trying to compute.\n\nIt is tempting to try  to reduce the first case to `*[a d]`. However, this reduction is incorrect. You may have a case where `*[a c]` crashes but `*[a d]` does not. In this case, a correct interpreter will crash the whole expression if `*[a c]` crashes, whereas an incorrect interpreter will proceed with `*[a d]`. Thus, all correct interpreters must try\nto compute `*[a c]`.\n\n`*[a 11 [b c] d] == *[[*[a c] *[a d]] 0 3]`  \n`== *[*[a c d] *[a 1 0 3]]`  \n`== *[a 2 [c d] 1 0 3]`  \n\n`*[a 11 b c] == *[a c]`  \n`== *[*[a 0 1] *[a 1 c]]`\n`== *[a 2 [0 1] 1 c]`\n\n### Nock 11 Primitive Equivalent\n`*[a 11 [b c] d] == *[a 2 [c d] 1 0 3]`  \n`*[a 11 b c] ====== *[a 2 [0 1] 1 c]`\n\n### Nock 11 Pseudocode Operator Equivalent\n`*[a 11 [b c] d] == /[3 [*[a c] *[a d]]]`  \n`*[a 11 b c] ====== *[a c]`\n\n## Finally: Nock 10\nFor convenience, let's restate Nock 10 and the `#` hax edit operator.\n\n`*[a 10 [b c] d] ==  #[b *[a c] *[a d]]`  \n\n`#[1 a b] ============ a`  \n`#[(a + a) b c] ====== #[a [b /[(a + a + 1) c]] c]`  \n`#[(a + a + 1) b c] == #[a [/[(a + a) c] b] c]`  \n\nNock 10 is defined in terms of the `#` hax edit operator. So let's derive this first.\n\n### Explaining the `#` hax edit operator\nLet's define `#` as a function of three inputs, `x`, `y`, and `z`. This says replace what's in slot `x` of `z` with `y`. In fact, let's rewrite the pseudocode with these inputs.\n\n`#[(x := 1) y z] ========= y`  \n`#[(x : x is even) y z] == #[x/2 [y /[x+1 z]] z]`  \n`#[(x : x is odd) y z] === #[(x-1)/2 [/[x-1 z] y] z]`  \n\n\nWhat are we doing here? Let's first note that there is really no way for us to \"edit\" a noun. Really what we are doing is producing a new noun which is exactly the same as the old noun except in the specified way. If `x` is `1`, we are slotting into the root address of the noun `z` and replacing it with `y`, so we can get our \"edited\" noun simply by returning `y`. For any `x` greater than `1`, however, we have to create an entirely new noun. But creating complex nouns from scratch is hard. Creating a single _cell_, on the other hand, is easy.\n\nTo make this easier to understand, let's say `v := /[x z]`. `v` is the noun we will be replacing with `y`; the current occupant of slot `x` in noun `z`.  This noun `v` has a \"sibling noun\" which we will call `w`. `v` is either the head or the tail of its \"parent noun\" `u`. Below, we diagram the two possible cases.\n\n```\n      z              z\n     / \\            / \\\n    *   *          *   *\n   / \\            / \\\n  u   *          u   *\n / \\            / \\\nv   w          w   v\n```\n\nWhile we cannot create a modifed `z` in one step, we can create a modified `u` in one step. `u == [v w]` or `u == [w v]`. Since we are replacing `v` with `y`, our modified `u` looks like `u' == [y w]` in the first case and `u' == [w y]` in the second case. We already have `y`. We need to figure out how to get `w` and how to replace `u`. This requires the addresses of both. We diagram this below.\n\n```\nnouns          slots\n-----          -----\n  u             x/2\n / \\            / \\ \nv   w          x  x+1\n\n  u           (x-1)/2\n / \\            / \\\nw   v         x-1  x\n```\n\nIf `x` is even, `w` is in slot `x+1` of `z` and `u' == [y /[x+1 z]]` can be slotted into slot `x/2` of `z`. If `x` is odd, `w` is in slot `x-1` of `z` and `u' == [/[x-1 z] y]` can be slotted into slot `(x-1)/2` of `z`. A more concise way to say this would be:\n\n`#[(x : x is even) y z] == #[x/2 [y /[x+1 z]] z]`  \n`#[(x : x is odd) y z] === #[(x-1)/2 [/[x-1 z] y] z]`  \n\nThis operation will recur, and since the slot is always getting smaller, we will eventually get to the base case of `x == 1` at which point we will return our new \"edited\" noun.\n\nNow let's translate this into Nock.\n\n### Translating the `#` hax edit operator into Nock\n_To perform this translation, we are going to make liberal use of dojo variables to keep things relatively simple and modular._\n\nWe are trying to recreate the `#` hax edit operator in a function called `hax` which will take a subject `[x y z]`.  We should be able to run:\n\n`*[[x y z] hax] == #[x y z]`.\n\n\n#### Avoiding Degenerate Cases\nLet's crash immediately if `x` is a cell. This will make use of Nock 6. If `x-is-cell`, then `crash`; else `check-x-0` (we will proceed to checking another degenerate case):\n\n`*[[x y z] 6 x-is-cell crash check-x-0]`\n\nFor the sake of our OCD, we can start to convert this to Nocks 0 through 5 using our definition:\n\n`*[a 6 b c d] == *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]`\n\n`=hax [2 [0 1] 2 [1 crash check-x-0] [1 0] 2 [1 2 3] [1 0] 4 4 x-is-cell]`\n\nTo check if `x` is a cell, we use Nock 3:\n\n`*[[x y z] 3 0 2]`  \n`=x-is-cell [3 0 2]`  \n\nTo crash, we can simply try to slot into non-existing address `0`:\n\n`*[[x y z] 0 0]`  \n`=crash [0 0]`  \n\nWe should also crash if `x == 0`:\n\n`*[[x y z] 6 x-is-0 crash launch]`  \n`=check-x-0 [2 [0 1] 2 [1 crash launch] [1 0] 2 [1 2 3] [1 0] 4 4 x-is-0]`\n\nTo check if `x == 0`, we use Nock 5:\n\n`*[[x y z] 5 [0 2] 1 0]`  \n`=x-is-0 [5 [0 2] 1 0]`\n\n#### Launching the Main Formula\nIn order to make recursive calls, we are going to want to store our formula in the head of our subject so that we can access it from within the formula.\n\n`[hax-formula x y z]`  \n\nWe can do this with Nock 8 and Nock 9. With Nock 8, we will pin `hax-formula` to the head of the subject and then call this head on the modified subject using Nock 9.\n\n`*[[x y z] 8 [1 hax-formula] call-head]`  \n\nRecall: `*[a 8 b c] == *[a 2 [b 0 1] 1 c]`  \n\n`=launch [2 [[1 hax-formula] 0 1] 1 call-head]`\n\nTo call the head of the modified subject on itself:\n\n`*[[hax-formula x y z] 9 2 0 1]`\n\nRecall: `*[a 9 b c] == *[a 2 c 1 2 [0 1] 0 b]`  \n\n`*[[hax-formula x y z] 9 2 0 1] == [[hax-formula x y z] 2 [0 1] 1 2 [0 1] 0 2]`\n\nNotice that this simplifies to:\n\n`=call-head [2 [0 1] 0 2]`\n\n#### Base Case\nNow let's develop `hax-formula`. The subject we are now dealing with has the form:\n\n`[hax-formula x y z]`  \n\n* `hax-formula` is at slot `2` (the head)\n* `x` is at slot `6` (the head of the tail)\n* `y` is at slot `14`\n* `z` is at slot `15`\n\nLet's deal with the first real branch.  If `x == 1`, then we return `y`; else, we `recur-hax`:\n\n`*[[hax-formula x y z] 6 x-is-1 return-y recur-hax]`  \n`=hax-formula [2 [0 1] 2 [1 return-y recur-hax] [1 0] 2 [1 2 3] [1 0] 4 4 x-is-1]`  \n`=x-is-1 [5 [0 6] 1 1]`  \n`=return-y [0 14]`\n\n#### Recursion\nExcellent. Now we are getting to the recursive part of our algorithm. We have already dealt with the base case. Now in the non-base case we want to call `hax-formula` on new parameters `[new-x new-y new-z]`. Let us imagine that there is a function `new-params` which takes subject `[x y z]` and returns `[new-x new-y new-z]`.  We can write this function later.\n\nFirst, we want to create a cell:\n\n`[hax-formula new-x new-y new-z] == [hax-formula *[[x y z] new-params]]`\n\n`*[[hax-formula x y z] [0 2] 2 [0 3] 1 new-params]`  \n`=new-cell [[0 2] 2 [0 3] 1 new-params]`\n\nAnd we want to call the head of this new cell on itself:\n\n`*[[hax-formula x y z] 9 2 new-cell]`  \n`=recur-hax [2 new-cell 1 2 [0 1] 0 2]`\n\n#### Getting the New Parameters\nWhen trying to extract new parameters from `[x y z]`, we come to another branch. We know at this point that `x` is not a cell and `x \u003e 1`. Now we need to check if `x` is even:\n\nIf `x` is even, return the following parameter updates:\n\n`x := x/2`  \n`y := [y /[x+1 z]]`  \n`z := z`  \n\nElse (if `x` is odd), return the following parameter updates:\n\n`x := (x-1)/2`  \n`y := [/[x-1 z] y]`  \n`z := z`  \n\nSo there are basically three things we need. We need a decremented `x`, `x-1`. We need a loobean which returns `0` if `x` is even and `1` otherwise (if `x` is odd; we have already dealt with all other cases). And we need the floor of half of `x`--the \"parent address\" of `x`.\n\nWe can actually get all of these at the same time. By using a modified version of the decrement algorithm, we can count up to `x-1` using some `counter` variable, keep track of whether `counter+1` is even or odd in variable `iseven` and keep track of the \"parent address\" of `counter+1` in variable `floorhalf`. When we get to `counter == x-1` we will have `x-1`, whether `x` is even, and the floor of half of `x`.\n\nBecause we are dealing with `x` values greater than `1`, the initial value of `counter` is `1`. Since the initial value of `counter+1` is `2` (the lowest possible value of `x`), the initial value of `iseven` is `0` and the initial value of `floorhalf` is `1`.\n\nHere is what this looks like counting up to 10:\n\n```\n                     -------\n                     x == 10\n                     -------\n+(counter)  2  3  4  5  6  7  8  9 10\ncounter     1  2  3  4  5  6  7  8  9\niseven      0  1  0  1  0  1  0  1  0\nfloorhalf   1  1  2  2  3  3  4  4  5\n```\n\n#### Implementing `new-params`\nLet's look at the format of our function. Our subject is `[x y z]`. We are going to pin `[counter iseven floorhalf]` to the head of this noun and then our `params-formula` for recursion to the head of that. So by the time our recursion starts, our subject will look like this:\n\n`[params-formula [counter iseven floorhalf] x y z]`\n\nTo pin `[[counter == 1] [iseven == 0] [floorhalf == 1]]` to the head of subject `[x y z]`, we run:\n\n`*[[x y z] 8 [1 1 0 1] pin-formula] == *[[[1 0 1] x y z] pin-formula]`  \n`=new-params [2 [[1 1 0 1] 0 1] 1 pin-formula]`\n\nNext, we want to pin our `params-formula` to the head of this new subject:\n\n`*[[[1 0 1] x y z] 8 [1 params-formula] call-head]`  \n`== *[[params-formula [1 0 1] x y z] call-head]`  \n`=pin-formula [2 [[1 params-formula] 0 1] 1 call-head]`  \n\nFinally, we want to run this `params-formula`, which is in the head of this new subject, against the whole subject. We actually already created a function which accomplishes this. We called it `call-head`.\n\n`call-head == [2 [0 1] 0 2]`\n\n#### The New Parameter Formula\nOkay. Now we're ready to develop `params-formula`, which operates on subject:\n\n`[params-formula [counter iseven floorhalf] x y z]`\n\n(To save space we will write this as `[pf [c i f] x y z]`.)\n\n* `params-formula` is at slot `2` (the head)\n* `counter` is at slot `12` (the head of the head of the tail)\n* `iseven` is at slot `26`\n* `floorhalf` is at slot `27` \n* `x` is at slot `14`\n* `y` is at slot `30`\n* `z` is at slot `31`\n\nOur formula should check if `counter+1 == x`. If this is the case, we have all the necessary data and we can `return-params`. Else, we should increment `counter`, flip `iseven` from `0` to `1` or from `1` to `0`, increment `floorhalf` only if `iseven == 1`, and then run `params-formula` again. You should be able to convince yourself that this works.\n\n`*[[pf [c i f] x y z] 6 is-at-x return-params recur-pf]`  \n`=params-formula [2 [0 1] 2 [1 return-params recur-pf] [1 0] 2 [1 2 3] [1 0] 4 4 is-at-x]`  \n\n`=is-at-x [5 [0 14] 4 0 12]`\n\n#### Returning the Parameters\nTo return parameters from `[pf [c i f] x y z]` we need to branch on `iseven`.\n\n`*[[pf [c i f] x y z] 6 iseven even-params odd-params]`  \n`=iseven [0 26]`  \n`=return-params [2 [0 1] 2 [1 even-params odd-params] [1 0] 2 [1 2 3] [1 0] 4 4 iseven]`\n\nRecall:\n\nIf `x` is even, return the following parameter updates:\n\n`x := x/2`  \n`y := [y /[x+1 z]]`  \n`z := z`  \n\nElse (if `x` is odd), return the following parameter updates:\n\n`x := (x-1)/2`  \n`y := [/[x-1 z] y]`  \n`z := z`  \n\nThis translates to:\n\nIf `iseven` is `0`, return: `[floorhalf [y /[+(x) z]] z]`.  \nElse, return: `[floorhalf [/[counter z] y] z]`.  \n\nLet's try to build these cells:\n\n`+(x) == *[[pf [c i f] x y z] 4 0 14]`  \n`counter == *[[pf [c i f] x y z] 0 12]`  \n`z == *[[pf [c i f] x y z] 0 31]`  \n\n`/[+(x) z] == *[z 0 +(x)]`  \n`== *[*[[pf [c i f] x y z] 0 31] *[[pf [c i f] x y z] [1 0] 4 0 14]]`  \n`== *[[pf [c i f] x y z] 2 [0 31] [1 0] 4 0 14]`\n\n`/[counter z] == *[z 0 counter]`  \n`== *[*[[pf [c i f] x y z] 0 31] *[[pf [c i f] x y z] [1 0] 0 12]]`  \n`== *[[pf [c i f] x y z] 2 [0 31] [1 0] 0 12]`  \n\n`[floorhalf [y /[+(x) z]] z]`  \n`== *[[pf [c i f] x y z] [0 27] [[0 30] 2 [0 31] [1 0] 4 0 14] 0 31]`  \n`=even-params [[0 27] [[0 30] 2 [0 31] [1 0] 4 0 14] 0 31]`  \n\n`[floorhalf [/[counter z] y] z]`  \n`== *[[pf [c i f] x y z] [0 27] [[2 [0 31] [1 0] 0 12] 0 30] 0 31]`  \n`=odd-params [[0 27] [[2 [0 31] [1 0] 0 12] 0 30] 0 31]`  \n\nAlright. We now have a formula to return new parameters when `x` is even and a formula to return new parameters when `x` is odd.\n\n#### Recurring the Modified Decrement\nNow we need to actually get our modified decrement to count up to `x-1`, updating our other data with it. Remember, our `recur-pf` formula will be operating on subject:  \n\n`[params-formula [counter iseven floorhalf] x y z]`  \n\nWe want to call `params-formula` on:\n\n`[params-formula [new-counter new-iseven new-floorhalf] x y z]`\n\nWe can do this by calling:\n\n\n`*[[pf [c i f] x y z] 9 2 [0 2] [new-counter new-iseven new-floorhalf] 0 7]`  \n\n`[[0 2] [new-counter new-iseven new-floorhalf 0 7]]` creates the new subject as a cell and the `9` launches the head `2` on this new subject.\n\n`=recur-pf [2 [[0 2] [new-counter new-iseven new-floorhalf] 0 7] 1 2 [0 1] 0 2]`  \n\n#### Actually Counting\nNow let's actually update these values. `new-counter` is easy enough. It just increments the existing counter.\n\n`=new-counter [4 0 12]`\n\n`new-iseven` checks `iseven` then returns `1` if yes or `0` if no.  \n`*[[pf [c i f] x y z] 6 iseven [1 1] 1 0]`  \n`=new-iseven [2 [0 1] 2 [1 [1 1] 1 0] [1 0] 2 [1 2 3] [1 0] 4 4 iseven]`  \n\n`new-floorhalf` checks `iseven` and returns `floorhalf` if yes or\n`+(floorhalf)` if no.\n\n`*[[pf [c i f] x y z] 6 iseven [0 27] 4 0 27]`  \n`=new-floorhalf [2 [0 1] 2 [1 [0 27] 4 0 27] [1 0] 2 [1 2 3] [1 0] 4 4 iseven]`  \n\n#### Building Our Formula in Dojo\nOkay! We have written our `#` hax edit operator as a Nock formula consisting of only Nocks 0 through 5. Very exciting! Let's put it together and see what it looks like. If you would like to try this yourself, copy and paste the following code in the dojo.\n\n```\n=iseven [0 26]\n=new-counter [4 0 12]\n=new-iseven [2 [0 1] 2 [1 [1 1] 1 0] [1 0] 2 [1 2 3] [1 0] 4 4 iseven]\n=new-floorhalf [2 [0 1] 2 [1 [0 27] 4 0 27] [1 0] 2 [1 2 3] [1 0] 4 4 iseven]\n=recur-pf [2 [[0 2] [new-counter new-iseven new-floorhalf] 0 7] 1 2 [0 1] 0 2] \n=odd-params [[0 27] [[2 [0 31] [1 0] 0 12] 0 30] 0 31]\n=even-params [[0 27] [[0 30] 2 [0 31] [1 0] 4 0 14] 0 31]\n=return-params [2 [0 1] 2 [1 even-params odd-params] [1 0] 2 [1 2 3] [1 0] 4 4 iseven]\n=is-at-x [5 [0 14] 4 0 12]\n=params-formula [2 [0 1] 2 [1 return-params recur-pf] [1 0] 2 [1 2 3] [1 0] 4 4 is-at-x]\n=call-head [2 [0 1] 0 2]\n=pin-formula [2 [[1 params-formula] 0 1] 1 call-head]\n=new-params [2 [[1 1 0 1] 0 1] 1 pin-formula]\n=new-cell [[0 2] 2 [0 3] 1 new-params]\n=recur-hax [2 new-cell 1 2 [0 1] 0 2]\n=x-is-1 [5 [0 6] 1 1]\n=return-y [0 14]\n=hax-formula [2 [0 1] 2 [1 return-y recur-hax] [1 0] 2 [1 2 3] [1 0] 4 4 x-is-1]\n=launch [2 [[1 hax-formula] 0 1] 1 call-head]\n=x-is-0 [5 [0 2] 1 0]\n=crash [0 0]\n=check-x-0 [2 [0 1] 2 [1 crash launch] [1 0] 2 [1 2 3] [1 0] 4 4 x-is-0]\n=x-is-cell [3 0 2]\n\n=hax [2 [0 1] 2 [1 crash check-x-0] [1 0] 2 [1 2 3] [1 0] 4 4 x-is-cell]\n\n=iseven\n=new-counter\n=new-iseven\n=new-floorhalf\n=recur-pf\n=odd-params\n=even-params\n=return-params\n=is-at-x\n=params-formula\n=call-head\n=pin-formula\n=new-params\n=new-cell\n=recur-hax\n=x-is-1\n=return-y\n=hax-formula\n=launch\n=x-is-0\n=crash\n=check-x-0\n=x-is-cell\n\nhax\n```\n\nGreat! What does this look like?\n\n```\n[ 2\n  [0 1]\n  2\n  [ 1\n    [0 0]\n    2\n    [0 1]\n    2\n    [ 1\n      [0 0]\n      2\n      [ [ 1\n          2\n          [0 1]\n          2\n          [ 1\n            [0 14]\n            2\n            [ [0 2]\n              2\n              [0 3]\n              1\n              2\n              [[1 1 0 1] 0 1]\n              1\n              2\n              [ [ 1\n                  2\n                  [0 1]\n                  2\n                  [ 1\n                    [ 2\n                      [0 1]\n                      2\n                      [ 1\n                        [[0 27] [[0 30] 2 [0 31] [1 0] 4 0 14] 0 31]\n                        [0 27]\n                        [[2 [0 31] [1 0] 0 12] 0 30]\n                        0\n                        31\n                      ]\n                      [1 0]\n                      2\n                      [1 2 3]\n                      [1 0]\n                      4\n                      4\n                      0\n                      26\n                    ]\n                    2\n                    [ [0 2]\n                      [ [4 0 12]\n                        [2 [0 1] 2 [1 [1 1] 1 0] [1 0] 2 [1 2 3] [1 0] 4 4 0 26]\n                        2\n                        [0 1]\n                        2\n                        [1 [0 27] 4 0 27]\n                        [1 0]\n                        2\n                        [1 2 3]\n                        [1 0]\n                        4\n                        4\n                        0\n                        26\n                      ]\n                      0\n                      7\n                    ]\n                    1\n                    2\n                    [0 1]\n                    0\n                    2\n                  ]\n                  [1 0]\n                  2\n                  [1 2 3]\n                  [1 0]\n                  4\n                  4\n                  5\n                  [0 14]\n                  4\n                  0\n                  12\n                ]\n                0\n                1\n              ]\n              1\n              2\n              [0 1]\n              0\n              2\n            ]\n            1\n            2\n            [0 1]\n            0\n            2\n          ]\n          [1 0]\n          2\n          [1 2 3]\n          [1 0]\n          4\n          4\n          5\n          [0 6]\n          1\n          1\n        ]\n        0\n        1\n      ]\n      1\n      2\n      [0 1]\n      0\n      2\n    ]\n    [1 0]\n    2\n    [1 2 3]\n    [1 0]\n    4\n    4\n    5\n    [0 2]\n    1\n    0\n  ]\n  [1 0]\n  2\n  [1 2 3]\n  [1 0]\n  4\n  4\n  3\n  0\n  2\n]\n```\n\nQuite a mouthful. I don't think this one will fit on a t-shirt. \nMaybe an evening gown? Or perhaps a toga.\n\nSo, does it work?\n```\n\u003e .*([1 [4 5] 6 7 8 9 10 11 12 13] hax)\n[4 5]\n\n\u003e .*([2 [4 5] 6 7 8 9 10 11 12 13] hax)\n[[4 5] 7 8 9 10 11 12 13]\n\n\u003e .*([3 [4 5] 6 7 8 9 10 11 12 13] hax)\n[6 4 5]\n\n\u003e .*([62 [4 5] 6 7 8 9 10 11 12 13] hax)\n[6 7 8 9 [4 5] 11 12 13]\n\n\u003e .*([17 [4 5] [[[[[[[6] 7] 8] 9] 10] 11] 12] 13] hax)\n[[[[[[[6 7] 8] 9] 4 5] 11] 12] 13]\n```\n\nIt appears so! We are inches away from the finish line.\n\n### Nock 10 using only Nocks 0 through 5\nWe have our hax operator. The last thing we have to do is use it to create a Nock 10 which runs on subject `a` with parameters `b`, `c`, and `d`:\n\n`*[a 10 [b c] d] == #[b *[a c] *[a d]]`\n\nRecall that we wrote `hax` such that:\n\n`*[[x y z] hax] == #[x y z]`  \n\nWe can now rewrite this as:\n\n`*[a 10 [b c] d] == *[[b *[a c] *[a d]] hax]`  \n`== *[[*[a 1 b] *[a c d]] *[a 1 hax]]`  \n`== *[*[a [1 b] c d] *[a 1 hax]]`  \n`== *[a 2 [[1 b] c d] 1 hax]`  \n`=nock-ten [2 [[1 b] c d] 1 hax]`\n\nAnd that's it. Congratulations! You have now derived all the Nock opcodes from 6 to 11 using only opcodes 0 through 5. What you will accomplish with this knowledge, I tremble to imagine.\n\n### Nock 10 Primitive Equivalent\n```\n*[a 10 [b c] d] ==\n\n*[a 2\n  [[1 b] c d]\n  1\n  2\n  [0 1]\n  2\n  [ 1\n    [0 0]\n    2\n    [0 1]\n    2\n    [ 1\n      [0 0]\n      2\n      [ [ 1\n          2\n          [0 1]\n          2\n          [ 1\n            [0 14]\n            2\n            [ [0 2]\n              2\n              [0 3]\n              1\n              2\n              [[1 1 0 1] 0 1]\n              1\n              2\n              [ [ 1\n                  2\n                  [0 1]\n                  2\n                  [ 1\n                    [ 2\n                      [0 1]\n                      2\n                      [ 1\n                        [[0 27] [[0 30] 2 [0 31] [1 0] 4 0 14] 0 31]\n                        [0 27]\n                        [[2 [0 31] [1 0] 0 12] 0 30]\n                        0\n                        31\n                      ]\n                      [1 0]\n                      2\n                      [1 2 3]\n                      [1 0]\n                      4\n                      4\n                      0\n                      26\n                    ]\n                    2\n                    [ [0 2]\n                      [ [4 0 12]\n                        [2 [0 1] 2 [1 [1 1] 1 0] [1 0] 2 [1 2 3] [1 0] 4 4 0 26]\n                        2\n                        [0 1]\n                        2\n                        [1 [0 27] 4 0 27]\n                        [1 0]\n                        2\n                        [1 2 3]\n                        [1 0]\n                        4\n                        4\n                        0\n                        26\n                      ]\n                      0\n                      7\n                    ]\n                    1\n                    2\n                    [0 1]\n                    0\n                    2\n                  ]\n                  [1 0]\n                  2\n                  [1 2 3]\n                  [1 0]\n                  4\n                  4\n                  5\n                  [0 14]\n                  4\n                  0\n                  12\n                ]\n                0\n                1\n              ]\n              1\n              2\n              [0 1]\n              0\n              2\n            ]\n            1\n            2\n            [0 1]\n            0\n            2\n          ]\n          [1 0]\n          2\n          [1 2 3]\n          [1 0]\n          4\n          4\n          5\n          [0 6]\n          1\n          1\n        ]\n        0\n        1\n      ]\n      1\n      2\n      [0 1]\n      0\n      2\n    ]\n    [1 0]\n    2\n    [1 2 3]\n    [1 0]\n    4\n    4\n    5\n    [0 2]\n    1\n    0\n  ]\n  [1 0]\n  2\n  [1 2 3]\n  [1 0]\n  4\n  4\n  3\n  0\n  2\n]\n```\n\n\u003csup\u003e1\u003c/sup\u003e It goes without saying that this was a momentary slip of the tongue. The point is only that it is an easy mistake to make. ~rovnys-ricfer's \"Urbit From the Outside In\" is an excellent and highly recommended series.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniblyx-malnus%2FNock10Tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fniblyx-malnus%2FNock10Tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniblyx-malnus%2FNock10Tutorial/lists"}