The kcats Programming Language Lexicon

Table of Contents

1. Standard library source and documentation

1.1. Comparison

Words that help compare one item to another, with concepts of equal, greater, less etc.

[= [[spec [[item item] [boolean]]] 
    [examples [[[1 2 =] [🔳] "Different Numbers are not equal"]
               [[1 1 =] [] "Same numbers are equal"]
               [[1 1.0 =] [] "Same value integer and float are equal"]
               [[[1] 🔳 =]  [🔳] "Number and Nothing are unequal"]
               [[[1 [🔳]] [1 [🔳]] =] [] "Same nested list with numbers are equal"]
               [[[1.0 ["foo"]] [1.0 ["foo"]] =] [] "Same nested list with string are equal"]
               [["hi" "hi" =] [] "Same strings are equal"]
               [["hi" "there" =] [🔳] "Different strings are unequal"]
               [[\h \h =] [] "Same characters are equal"]
               [[\h \i =] [🔳] "Different characters are unequal"]
               [["hi" encode "hi" encode =] [] "Same bytes are equal"]
               [["hi" encode "there" encode =] [🔳] "Different bytes are unequal"]
               [[🔳 ✅ =] [🔳] "Different booleans unequal"]
               [[[1.0 ["foo"]] [1.0 ["bar"]] =]  [🔳] "Nested lists with different strings are unequal"]
               [[🔳 🔳 =] [] "'Nothing' is equal to itself"]
               [[🔳 🔳 association =] [] "List/Association empty container types are equal"]
               [[🔳 🔳 set =] [] "List/Set empty container types are equal"]
               [[[[a b]] [[a b]] association =] [🔳] "Nonempty List/Association types are unequal"]
               [[[1 2 3] set [3 1 2] set =] [] "Sets constructed from different lists are equal"]
               [[["foo" =] [🗑️ "Needs 2 items"] 🩹 ▶️] ["Needs 2 items"] "Less than 2 stack items results in an error"]]]]]

[compare [[spec [[item item] [word]]]
          [examples [[["a" "b" compare] [[less] 🍫] "string lexicographical order with single character inequality"]
                     [["a" "a" compare] [[equal] 🍫] "string lexicographical order with single character equality"]
                     [[1 1 compare] [[equal] 🍫] "Same integer compares equal"]
                     [[2 1 compare] [[greater] 🍫] "Integer order inequality"]
                     [[1 [foo] 🍫 compare] [[less] 🍫] "Integer/list order inequality"]
                     [[1 "foo" encode compare] [[less] 🍫] "Integer/byte order inequality"]
                     [[[foo] 🍫 "foo" encode compare] [[less] 🍫] "Word/string order inequality"]
                     [["foo" encode "foo" compare] [[less] 🍫] "String order equaltiy"]
                     [[🔳 [🔳] 🍫 compare] [[equal] 🍫] "Unwrapped Nothing value equality"]
                     [[🔳 [1] rest compare] [[equal] 🍫] "Nothing/emptied container equality"]
                     [[["foo" compare] [🗑️ "Needs 2 items"] 🩹 ▶️] ["Needs 2 items"] "Less than 2 stack items results in an error"]

                     ;; Length comparisons
                     [["ab" "a" compare] [[greater] 🍫] "Longer string is greater"]
                     [["" "" compare] [[equal] 🍫] "Empty strings are equal"]
                     [["" "a" compare] [[less] 🍫] "Empty string is less than non-empty"]

                     ;; List comparisons
                     [[[1 2] [1 2] compare] [[equal] 🍫] "Equal lists compare equal"]
                     [[[1 2] [1 3] compare] [[less] 🍫] "Lists compared element by element"]
                     [[[1 2 3] [1 2] compare] [[greater] 🍫] "Longer list is greater"]
                     [[🔳 🔳 compare] [[equal] 🍫] "Empty lists are equal"]
                     [[🔳 [1] compare] [[less] 🍫] "Empty list is less than non-empty"]

                     ;; Mixed type edge cases
                     [[🔳 "" compare] [[greater] 🍫] "Empty list vs empty string"]
                     [[[🔳] 🔳 compare] [[greater] 🍫] "Nothing in list vs bare Nothing"]
                     [[[""] 🔳 compare] [[greater] 🍫] "List with empty string vs empty list"]

                     ;; Number edge cases
                     [[0 -0 compare] [[equal] 🍫] "Zero equals negative zero"]
                     [[42 42.0 compare] [[equal] 🍫] "Integer equals float representation"]
                     [[-1 1 compare] [[less] 🍫] "Negative less than positive"]

                     ;; Unicode string comparisons
                     [["é" "e" compare] [[greater] 🍫] "Accented character comparison"]
                     [["a" "A" compare] [[greater] 🍫] "Case-sensitive comparison"]
                     [["🍫" "a" compare] [[greater] 🍫] "Emoji vs ASCII"]

                     ;; Nested structure comparisons
                     [[[1 [2]] [1 [2]] compare] [[equal] 🍫] "Nested structure equality"]
                     [[[1 [2]] [1 [3]] compare] [[less] 🍫] "Nested structure inequality"]
                     [[[🔳 🔳] [🔳 🔳] compare] [[equal] 🍫] "Different arrangements of Nothing and empty list"]]]]]

[compare-by [[spec [[program [item a] [item b]] [word]]]
             [definition [👥
                          [▶️] 🐋 
                          [▶️] 🪄 
                          compare]]
             [examples [[[-1 -2 [abs] compare-by] [[less] 🍫]]]]]]

[< [[spec [[[item a] [item b]] [boolean]]]
    [definition [🔳 compare-by [less] 🍫 =]]
    [examples [[[1 2 <] [] "Integer is less"]
               [[2.2 1.1 <] [🔳] "Float is not less"]
               [[1 2.2 <] [] "Integer/float is less"]
               [[-3 2.2 <] [] "Negative integer/float is less"]
               [[0 2.2 <] [] "Zero Integer/float is less"]
               [[1.1 1.1 <] [🔳] "Equal floats is not less"]
               [[-1.1 -1.1 <] [🔳] "Negative equal floats is not less"]
               [["a" "b" <] [] "String is less than other string"]
               [[["a" "b"] ["a" "c"] <] [] "List is less than other list"]]]]]

[> [[spec [[[item a] [item b]] [boolean]]]
    [definition [🔳 compare-by [greater] 🍫 =]]
    [examples [[[2 1 >] [] "Integer is greater"]
               [[1.1 2.2 >] [🔳] "Float is not greater"]
               [[2.2 1 >] [] "Integer/float is greater"]
               [[-1 -2.2 >] [] "Negative integer/float is greater"]
               [[0 -2.2 >] [] "Zero Integer/float is greater"]
               [[1.1 1.1 >] [🔳] "Equal floats is not greater"]
               [[-1.1 -1.1 >] [🔳] "Negative equal floats is not greater"]]]]]

[<= [[spec [[[item a] [item b]] [boolean]]]
     [definition [> ☯️]]
     [examples [[[1 2 <=] [] "Integer is less/equal"]
                [[2.2 1.1 <=] [🔳] "Float is not less/equal"]
                [[1 2.2 <=] [] "Integer/float is less/equal"]
                [[1.1 1.1 <=] [] "Equal floats is less/equal"]]]]]

[>= [[spec [[[item a] [item b]] [boolean]]]
     [definition [< ☯️]]
     [examples [[[2 1 >=] [] "Integer is greater/equal"]
                [[1.1 2.2 >=] [🔳] "Float is not greater/equal"]
                [[2.2 1 >=] [] "Integer/float is greater/equal"]
                [[1.1 1.1 >=] [] "Equal floats is greater/equal"]]]]]

[max-by [[spec [[program [item a] [item b]] [item]]]
         [definition [[compare-by 🎁] •🛡️ ▶️ [less] =
                      [🗑️ •🗑️] [🗑️] ↔️]]
         [examples [[[[[price 25] [name bar]]
                      [[price 15] [name foo]]
                      [[price] 🔍] max-by] [[[price 25] [name bar]]]]]]]]

[min-by [[spec [[program [item a] [item b]] [item]]]
         [definition [[compare-by 🎁] •🛡️ ▶️ [greater] =
                      [🗑️ •🗑️] [🗑️] ↔️]]
         [examples [[[[[price 25] [name bar]]
                      [[price 15] [name foo]]
                      [[price] 🔍] min-by] [[[price 15] [name foo]]]]]]]]

[min [[spec [[number number] [number]]]
      [definition [[<] 🛡️ [🗑️] [🔀] ⚖️ ▶️ 🗑️]]
      [examples [[[2 3 min] [2] "Smaller of two positive integers"]
                 [[-5 -3 min] [-5] "Smaller of two negative integers"]
                 [[0.3 0.2 min] [0.2] "Smaller of two floats <1"]]]]]

[max [[spec [[number number] [number]]]
      [definition [[>] 🛡️ [🗑️] [🔀] ⚖️ ▶️ 🗑️]]
      [examples [[[2 3 max] [3] "Larger of two positive integers"]
                 [[-5 -3 max] [-3] "Larger of two positive integers"]
                 [[0.3 0.2 max] [0.3] "Larger of two floats <1"]]]]]

1.2. Stack Ops

[🗑️ [[spec [[item] 🔳]]
    [doc "The trash can denotes throwing away a value, from the ToS."]
    [examples [[[1 2 3 🗑️] [1 2] "Drop integer on ToS"]
               [[1 2 3 [a b c] 🗑️] [1 2 3] "Drop list on ToS"]

               ;; Different types of values
               [[🔳 🗑️] 🔳 "Drop Nothing value"]
               [["hello" 🗑️] 🔳 "Drop string"]
               [[42.5 🗑️] 🔳 "Drop float"]
               [[✅ 🗑️] 🔳 "Drop boolean"]

               ;; Nested structures
               [[[1 [2 3] 4] 🗑️] 🔳 "Drop complex nested structure"]
               [[[[🔳]] 🗑️] 🔳 "Drop deeply nested empty lists"]

               ;; Multiple operations
               [[1 2 3 🗑️ 🗑️] [1] "Drop multiple times"]
               [[1 2 3 🗑️ 4 🗑️] [1 2] "Interleaved drops with pushes"]

               ;; Edge cases
               [[🔳 🗑️] 🔳 "Drop empty list"]
               [["" 🗑️] 🔳 "Drop empty string"]
               [[1 2 [🗑️] 🗑️] [1 2] "Drop list containing trash symbol"]

               ;; Error cases
               [[[🗑️] [🗑️ "Nothing to drop"] 🩹 ▶️] ["Nothing to drop"] "Empty stack results in error"]
               [[[1 🗑️ 🗑️] [🗑️ "Nothing to drop"] 🩹 ▶️] ["Nothing to drop"] "Multiple drops on nonempty stack"]]]]]

[👥 [[spec [[[item a]]
            [[item a] [item a]]]]
     [doc "The twins denote copying the ToS."]
     [examples [[[1 2 3 👥] [1 2 3 3] "Clone integer on ToS"]
                [["foo" "bar" "baz" 👥] ["foo" "bar" "baz" "baz"] "Clone string on ToS"]
                [[[👥] [🗑️ "Nothing to clone"] 🩹 ▶️] ["Nothing to clone"] "Empty stack results in error"]

                ;; Different types of values
                [[🔳 👥] [🔳 🔳] "Clone Nothing value"]
                [[✅ 👥] [✅ ✅] "Clone boolean"]
                [[42.5 👥] [42.5 42.5] "Clone float"]
                [[🔳 👥] [🔳 🔳] "Clone empty list"]

                ;; Nested structures
                [[[1 2 3] 👥] [[1 2 3] [1 2 3]] "Clone list"]
                [[[1 [2 [3]]] 👥] [[1 [2 [3]]] [1 [2 [3]]]] "Clone nested structure"]
                [[[👥] 👥] [[👥] [👥]] "Clone list containing clone symbol"]

                ;; Multiple operations
                [[1 👥 👥] [1 1 1] "Multiple consecutive clones"]
                [[1 2 👥 3 👥] [1 2 2 3 3] "Interleaved clones with pushes"]
                [[1 👥 🗑️] [1] "Clone then trash"]
                [[1 2 👥 👥 🗑️] [1 2 2] "Multiple clones then trash"]

                ;; Edge cases
                [["" 👥] ["" ""] "Clone empty string"]
                [[[🔳 🔳] 👥] [[🔳 🔳] [🔳 🔳]] "Clone complex structure with Nothing"]
                [[[[🔳]] 👥] [[[🔳]] [[🔳]]] "Clone nested empty lists"]

                ;; Error cases
                [[[👥 👥] [🗑️ "Nothing to clone"] 🩹 ▶️] ["Nothing to clone"] "Clone on empty stack"]
                [[1 🗑️ [👥] [🗑️ "Nothing to clone"] 🩹 ▶️] ["Nothing to clone" ] "Clone after emptying stack"]]]]]

[🧦 [[spec [[list] [list *]]]
     [doc "The socks denote a thing that is turned inside-out. Takes a list on ToS, makes it the new stack, and takes what had
              previously been the rest of the stack, and makes it a list on top
              of the new stack. Used for context switching."]
     [examples [[[1 2 3 [4 5 6] 🧦] [6 5 4 [3 2 1]] "Swap a list of integers with the rest of the stack"]
                [[1 [2] 3 [4 foo "bar"] 🧦] ["bar" [foo] 🍫 4 [3 [2] 1]] "Swap a list of items with the rest of the stack"]
                [[[4 5 6] 🧦] [6 5 4 🔳] "Swap a list of integers with an empty stack"]
                [[["a" "b" "c"] 🧦] ["c" "b" "a" 🔳] "Swap a list of strings with an empty stack"]
                [[[1 2 3 4 🧦] [🗑️ "List is required"] 🩹 ▶️] ["List is required"] "Non-list item result in an error"]
                [[[🧦] [🗑️ "Nothing to evert"] 🩹 ▶️] ["Nothing to evert"] "Empty stack results in error"]

                ;; Empty and single-item cases
                [[🔳 🧦] [🔳] "Evert empty list"]
                [[[1] 🧦] [1 🔳] "Evert single-item list"]
                [[2 [1] 🧦] [1 [2]] "Evert single-item list with one item below"]

                ;; Nested structures
                [[[1 [2 3] 4] 🧦] [4 [2 3] 1 🔳] "Evert list containing nested list"]
                [[[1 🔳 2] 🧦] [2 🔳 1 🔳] "Evert list containing empty list"]
                [[1 2 [[3 4] 5] 🧦] [5 [3 4] [2 1]] "Evert nested list with items below"]

                ;; Mixed types
                [[[✅ 🔳 "hello" 42] 🧦] [42 "hello" 🔳 ✅ 🔳] "Evert list of mixed types"]
                [[🔳 ["a" 1 ✅] 🧦] [✅ 1 "a" [🔳]] "Evert with Nothing below"]

                ;; Multiple operations
                [[1 [2 3] 🧦 [4 5] 🧦] [5 4 [[1] 2 3]] "Sequential everts"]
                [[1 [2 3] 🧦 👥] [3 2 [1] [1]] "Evert then clone"]
                [[1 2 [3 4] 🧦 🗑️] [4 3] "Evert then trash"]

                ;; Complex structures
                [[[1 [2 [3]] [4 [5]]] 🧦] [[4 [5]] [2 [3]] 1 🔳] "Evert deeply nested structure"]
                [[1 2 [🔳 🔳 [foo]] 🧦] [[foo] 🔳 🔳 [2 1]] "Evert list containing Nothing and empty list"]

                ;; Error cases
                [[1 2 3 [🧦] [🗑️ "List is required"] 🩹 ▶️] [1 2 3 "List is required"] "Try to evert non-list ToS"]
                [["hello" [🧦] [🗑️ "List is required"] 🩹 ▶️] ["hello" "List is required"] "Try to evert string"]
                [[1 2 3 [4 5] 🧦 🧦] [1 2 3 [4 5]] "Evert undoes itself"]]]]]
[•👥  [[spec [[[item a] [item b]]
              [[item a] [item b] [item b]]]]
       [doc "The twins with dot represents copying, one stack position down (copy the 2nd item)"]
       [definition [[👥] 🪄]]
       [examples [[[1 2 3 •👥] [1 2 2 3] "Clone the 2nd item on the stack"]]]]]


[••👥 [[spec [[[item a] [item b] [item c]]
              [[item a] [item b] [item c] [item c]]]]
       [doc "The twins with dots represents copying, two stack positions down (copy the 3rd item)"]
       [definition [[👥] •🪄]]
       [examples [[[1 2 3 4 ••👥] [1 2 2 3 4] "Clone the 3rd item on the stack"]]]]]

[over [[spec [[[item a] [item b]]
              [[item b] [item a] [item b]]]]
       [definition [•👥 🔀]]
       [examples [[[1 2 3 over] [1 2 3 2] "Copy the 2nd item to ToS"]]]]]

[under [[spec [[[item a] [item b]]
               [[item a] [item b] [item a]]]]
        [definition [👥 •🔀]]
        [examples [[[1 2 3 under] [1 3 2 3] "Copy the ToS to the 2nd item"]]]]]

[•🗑️ [[spec [[[item a] [item b]] [[item b]]]]
     [doc "The trash can with dot represents dropping, one stack position down (drop the 2nd item)"]
     [definition [🔀 🗑️]]
     [examples [[[1 2 3 •🗑️] [1 3] "Drop the 2nd item"]]]]]

[••🗑️ [[spec [[[item a] [item b] [item c]] [[item a] [item b]]]]
      [doc "The trash can with dots represents dropping, two stack position down (drop the 3rd item)"]
      [definition [🛟 🗑️]]
      [examples [[[1 2 3 ••🗑️] [2 3] "Drop the 3rd item"]]]]]

[📸 [[spec [🔳 [list]]]
     [doc "The camera denotes saving the whole stack as a list, on ToS."]
     [definition [🔳 🧦 👥 🧦 🍫]]
     [examples [[[1 2 3 📸] [1 2 3 [3 2 1]] "Copy the stack to ToS"]
                [[📸] [🔳] "Copy stack to ToS when stack is empty"]]]]]

[restore [[spec [[list] [*]]]
          [definition [🧦 🗑️]]
          [examples [[["x" "y" [1 2 3] restore] [3 2 1] "Replace stack with list"]
                     [[🔳 restore] 🔳 "Replace stack with empty list"]]]]]

1.2.1. Motion

These words change the order of items on the stack.

[🔀 [[spec [[[item a] [item b]]
            [[item b] [item a]]]]
     [doc "The crossing arrows denote swapping the top two stack items."]
     [examples [[[1 2 3 🔀] [1 3 2] "Swap top two items"]
                ;; Basic types
                [[🔳 ✅ 🔀] [✅ 🔳] "Swap boolean values"]
                [[42 "hello" 🔀] ["hello" 42] "Swap number and string"]
                [[🔳 "" 🔀] ["" 🔳] "Swap Nothing and empty string"]
                [["a" "b" 🔀] ["b" "a"] "Swap strings"]

                ;; Lists and nested structures
                [[[1 2] [3 4] 🔀] [[3 4] [1 2]] "Swap lists"]
                [[[1 [2]] [3 [4]] 🔀] [[3 [4]] [1 [2]]] "Swap nested lists"]
                [[[[🔳]] 🔳 🔀] [🔳 [[🔳]]] "Swap deeply nested empty list with empty list"]

                ;; Multiple operations
                [[1 2 3 🔀 🔀] [1 2 3] "Double swap"]
                [[1 2 🔀 3 🔀] [2 3 1] "Interleaved swaps"]
                [[1 2 🔀 🗑️] [2] "Swap then trash"]

                ;; With identical items
                [[42 42 🔀] [42 42] "Swap identical numbers"]
                [[🔳 🔳 🔀] [🔳 🔳] "Swap identical empty lists"]
                [[[1 2] [1 2] 🔀] [[1 2] [1 2]] "Swap identical complex lists"]

                ;; Error cases
                [[[🔀] [🗑️ "Need 2 items to swap"] 🩹 ▶️] ["Need 2 items to swap"] "Empty stack"]
                [[[1 🔀] [🗑️ "Need 2 items to swap"] 🩹 ▶️] ["Need 2 items to swap"] "Only one item on stack"]]]]]

[•🔀 [[spec [[[item a] [item b] [item c]]
             [[item a] [item c] [item b]]]]
      [doc "The crossing arrows with dot represents swapping one stack position down (2nd and 3rd items)"]
      [examples [[[1 2 3 •🔀] [2 1 3] "Swap 2nd and 3rd items"]]]]]

[🛟 [[spec [[[item a] [item b] [item c]]
            [[item c] [item a] [item b]]]]
     [doc "The buoy denotes floating the 3rd stack value to the top."]     
     [examples [[[1 2 3 🛟] [2 3 1] "Move 3rd item to ToS"]]]]]

[[[spec [[[item a] [item b] [item c]]
            [[item b] [item c] [item a]]]]
     [doc "The anchor denotes sinking the ToS to the 3rd position"]
     [examples [[[1 2 3 ⚓] [3 1 2] "Move ToS to 3rd item"]]]]]
[flip [[spec [[[item a] [item b] [item c]]
              [[item c] [item b] [item a]]]]
       [definition [🛟 •🔀]]
       [examples [[[1 2 3 flip] [3 2 1] "Swap ToS and 3rd item"]]]]]

1.3. Program execution

;; Input spec is item because builtins can be executed directly too
[▶️ [[spec [[item] [*]]]
    [doc "The 'play' arrow denotes running a program"]
    [examples [[[[1 2 +] ▶️] [3] "Execute a program"]
               [[1 2 🔳 ▶️] [1 2] "Execute an empty program"]

               ;; Nested execution
               [[1 2 [[+] ▶️] ▶️] [3] "Nested execution"]
               [[[1 [2 👥] ▶️ 3] ▶️] [1 2 2 3] "Execute nested program with clone"]

               ;; Multiple executions
               [[[1] ▶️ [2] ▶️] [1 2] "Sequential execution"]
               [[[[1] ▶️ [2 +] ▶️] ▶️] [3] "Nested sequential execution"]

               ;; Empty and Nothing cases
               [[🔳 ▶️] 🔳 "Execute empty program"]
               [[🔳 ▶️] 🔳 "Execute Nothing"]
               [[[🔳 [1] ▶️] ▶️] [🔳 1] "Execute Nothing then program"]

               ;; Complex programs
               [[[1 [2 +] ▶️ [3 +] ▶️] ▶️] [6] "Chained arithmetic operations"]
               [[[1 2 +] [3 4 *] 🔀 ▶️] [[3 4 *] 3] "Execute programs after swapping"]

               ;; Error handling
               [[[▶️] [🗑️ "Nothing to execute"] 🩹 ▶️] ["Nothing to execute"] "Try to execute with nothing on stack"]
               [[[1 ▶️] [🗑️ "Type error"] 🩹 ▶️] ["Type error"] "Try to execute a non program"]]]]]

[↔️ [[spec [[[program no-branch]
            [program yes-branch]
            [item condition]]
           [*]]]
    [doc "The left/right arrows denote choosing between two programs"]
    [examples [[[5 ✅ [🗑️ 3 *] [4 +] ↔️] [15] "Branch on true condition"]
               [[5 "hi" [🗑️ 3 *] [4 +] ↔️] [15] "Branch on truthy condition"]
               [[6 🔳 [3 *] [4 +] ↔️] [10] "Branch on false condition"]
               [[6 "" [3 *] [4 +] ↔️] [10] "Branch on falsey condition"]
               [[6 "hi" 🔳 [4 +] ↔️] [6 "hi"] "Branch with empty 'yes' program"]
               [[6 "" 🔳 🔳 ↔️] [6] "Branch with empty 'no' program"]]]]]

[🪄 [[spec [[program [item a]] [[item a] *]]]
     [doc "The magic wand denotes making ToS disappear while program runs, then reappear on ToS."]
     [examples [[[1 8 [inc] 🪄] [2 8] "Dipping a program under ToS"]
                [[1 2 [dec] 🍫
                  [+] 🪄] [3 [dec] 🍫] "A bare word on stack is left intact and not executed"]]]]]
[🪆 [[spec [[[program combinator]
             [program exit]
             [program body]
             [program pred]]
            [*]]]
     [doc "The Russian dolls denote a program recurrence. Constructs a recursive program, without having to give it a name.
           Takes 4 component programs as input: predicate, body, exit,
           and combinator; and returns a recursive program. This program will run predicate, if false the exit program
           runs and the recursive program is finished. If true, the body program runs, the whole recursive program is put on
           the stack and the combinator is run."]
     [definition [[✂️4️⃣
                   [✂️3️⃣ [4️⃣ 3️⃣ 2️⃣ 1️⃣ 🪆 ▶️] ✂️1️⃣]
                   2️⃣ ↔️] 🎒]]
     [examples [[[5
                  [2 >] 🛡️
                  [🗑️ 👥 dec] 🔳 [▶️ *]
                  🪆 ▶️]
                 [120]
                 "Recur with reduction"]]]]]

[🌀 [[spec [[program [item flag]] [*]]]
     [doc "The swirl denotes a programmatic loop with binary exit condition"]
     [definition [🔳 🔀 🔳 [▶️] 🪆]]
     [examples [[[10 ✅ [🗑️ -2 * 👥 50 <] 🌀 ▶️] [160] "Looping"]
                [[10 🔳 [🗑️ -2 * 👥 50 <] 🌀 ▶️] [10] "Looping with false initial condition is no-op"]]]]]


[decide [[spec [[[list test-expr-pairs]] [*]]]
         [doc "Takes a list of choices (pairs of test, program) and executes the first
               choice whose test passes. If none pass, it's a no-op. Stack is reset
               between testing conditions."]
         [definition [📤
                      [🍫 ;; break up the pair
                       🔀 
                       🛡️
                       ;; 🪆 
                       flip [1️⃣ decide] 🎒 ⚖️ ▶️]
                      [🗑️] ;; the empty container
                      ↔️]]
         [examples [[[5 [[[3 =] [🗑️ "three"]]
                         [[5 =] [🗑️ "five"]]
                         [[7 =] [🗑️ "seven"]]
                         [[] [🗑️ "something else"]]]
                      decide]
                     [5 "five"] "Decide with matching condition"]

                    [[9 [[[3 =] [🗑️ "three"]]
                         [[5 =] [🗑️ "five"]]
                         [[7 =] [🗑️ "seven"]]
                         [[] [🗑️ "something else"]]]
                      decide]

                     [9 "something else"] "Decide with matching default condition"]

                    [[9 [[[3 =] [🗑️ "three"]]
                         [[5 =] [🗑️ "five"]]
                         [[7 =] [🗑️ "seven"]]]
                      decide]
                     [9] "Decide with no matching condition"]]]]]

;; TODO: implement as axiom (which would depend on 'restore' which should also be axiom?)
[🛡️ [[spec [[program] [program]]]
    [doc "The shield denotes running a program, keeping top of stack produced, but protecting existing items from being consumed."]
    [definition [💉 [📸 ✂️1️⃣ first] 🎒]]
    [examples [[[1 2 3 [=] 🛡️ ▶️] [1 2 3 🔳] "Execute a program shielding the stack from consumption"]]]]]

[•🛡️ [[spec [[program] [program]]]
     [doc "The shield with dot denotes running a program, protecting all but the top stack item from being consumed."]
     [definition [💉 [📸 ✂️1️⃣ •🗑️ first] 🎒]]
     [examples [[[1 2 3 [=] •🛡️ ▶️] [1 2 🔳] "Execute a program consuming only the original ToS"]]]]]

[••🛡️ [[spec [[program] [program]]]
       [doc "The shield with dots denotes running a program, protecting all but the top two stack items from being consumed."]
      [definition [💉 [📸 ✂️1️⃣ •🗑️ •🗑️ first] 🎒]]
      [examples [[[1 2 3 [+ +] ••🛡️ ▶️] [1 6] "Execute a program consuming only the original top 2 items"]]]]]

[⚖️ [[spec [[[program no-branch]
            [program yes-branch]
            [program condition]]
           [program]]]
    [doc "The scales denote a choice between two programs, based on
          the binary resultof a test program"]
    [definition [[✂️3️⃣ ;; the condition
                  2️⃣ 1️⃣ ↔️] 🎒]]
    [examples [[[5 [👥 5 =] [🗑️ 3 *] [4 +] ⚖️ ▶️] [15] "Conditional with true predicate"]
               [[6 [👥 5 =] [🗑️ 3 *] [4 +] ⚖️ ▶️] [10] "Conditional with false predicate"]]]]]

[when [[spec [[[program yes-branch]
               [program condition]]
              [program]]]
       [definition [🔳 ⚖️]]
       [examples [[[3 [👥 odd?] [🗑️ inc] when ▶️] [4] "Conditional with no false branch and true predicate"]
                  [[3 [👥 even?] [🗑️ inc] when ▶️] [3] "Conditional with no false branch and false predicate"]]]]]

[dipped [[spec [program program]]
         [definition [[1️⃣ 🪄] 🎒]]]]

[•🪄 [[spec [[program
              [item a]
              [item b]]
             [[item a] [item b] *]]]
      [doc "The magic wand with dot denotes running a program, hiding
            the top two items and then making them reappear after the
            program is finished"]
      [definition [dipped dipped ▶️]]
      [examples [[[1 2 3 [inc] •🪄] [2 2 3] "Dip program under top two items"]]]]]

[••🪄 [[spec [[program
               [item a]
               [item b]
               [item c]]
              [[item a] [item b] [item c] *]]]
       [doc "The magic wand with dots denotes running a program,
             hiding the top three items and then making them reappear
             after the program is finished"]
       [definition [dipped dipped dipped ▶️]]
       [examples [[[1 2 3 4 [inc] ••🪄] [2 2 3 4] "Dip program under top 3 items"]]]]]

[🪜 [[spec [program program]]
     [doc "The ladder denotes a stepper, that iterates over a list and
           executes the program once per item. The rest of the list is
           hidden while the program runs."]
     [definition [[[📤 🔀 
                    1️⃣ 👥 •🪄
                    🪜 ▶️]
                   🔳 ↔️]
                  🎒]]
     [examples [[[1 [2 3 4] [*] 🪜 ▶️] [24] "Step through numbers doing arithmetic"]
                [[[1 2 3] [inc] 🪜 ▶️] [2 3 4] "Step through items"]
                [[1 🔳 [*] 🪜 ▶️] [1] "Stepping through empty list is no-op"]

                ;; Simple transformations
                [[[1 2 3] [👥] 🪜 ▶️] [1 1 2 2 3 3] "Double each item"]
                [[[1 2 3] [🗑️] 🪜 ▶️] 🔳 "Delete all items"]
                [[[1 2 3] 🔳 🪜 ▶️] [1 2 3] "No-op body"]
                [[[1 2 3] [🗑️ 🔳] 🪜 ▶️] [🔳 🔳 🔳] "Replace each item with Nothing"]

                ;; Different input types
                [[["a" "b" "c"] [encode] 🪜 ▶️] ["a" encode "b" encode "c" encode] "Convert each string to bytes"]
                [[[🔳 ✅ 🔳] [☯️] 🪜 ▶️] [✅ 🔳 ✅] "Step through list of booleans"]

                ;; Empty and single item cases
                [[[1] [👥] 🪜 ▶️] [1 1] "Step through single-item list"]
                [[[🔳] [👥] 🪜 ▶️] [🔳 🔳] "Step through list containing empty list"]

                ;; Nested lists
                [[[1 [2 3] 4] [🗑️] 🪜 ▶️] 🔳 "Step through list with nested structure"]
                [[[[1] [2] [3]] [first] 🪜 ▶️] [1 2 3] "Extract first item from each sublist"]

                ;; Stack manipulation within body
                [[[1 2 3] [42 🔀] 🪜 ▶️] [42 1 42 2 42 3] "Step and swap each item with constant"]
                [[[1 2 3] [👥 🔀] 🪜 ▶️] [1 1 2 2 3 3] "Clone and swap each item"]
                [[[1 2 3] [🗑️ 99] 🪜 ▶️] [99 99 99] "Remove and replace each item"]

                ;; Error cases
                [[[1 2 3] [🔀] [🪜 ▶️] [🗑️ "Error in body"] 🩹 ▶️] [[1 2 3] [🔀] "Error in body"] "Step body program causes error"]
                [[🔳 [1 0 /] 🪜 ▶️] 🔳 "Empty list with erroring body"]]]]]

[🐋 [[spec [[program [item a]] [item [item a] *]]]
     [doc "The whale denotes diving - running a program 'below' the
           ToS (with the ToS hidden from the program), and then
           surfacing the result up to the ToS (above the former
           ToS)."]
     [definition [🪄 🔀]]
     [examples [[[4 5 6 [+] 🐋] [6 9] "Dip program and move result to ToS"]]]]]

[•🐋 [[spec [[program [item a] [item b]]
             [item [item a] [item b] *]]]
      [doc "The whale with dot denotes running a program beneath the
            top two items, and then floating the result back to the
            ToS."]
      [definition [•🪄 🛟]]
      [examples [[[5 6 7 8 [+] •🐋] [7 8 11] "Dip under top 2 items and move result to ToS"]]]]]

[••🐋 [[spec [[program [item a] [item b] [item c]]
              [item [item a] [item b] [item c] *]]]
       [doc "The whale with dot denotes running a program beneath the
             top three items, and then floating the result back to the
             ToS."]
       [definition [🎁 [•🐋] 🔗 🪄 🔀]]
       [examples [[[4 5 6 7 8 [+] ••🐋] [6 7 8 9] "Dip under top 3 items and move result to ToS"]]]]]

[💉 [[spec [program program]]
     [doc "The syringe represents an injection - creates a program
           where it injects the given program into the list below it
           (runs the program with the list as its stack).  Does not
           affect the rest of the stack."]
     [definition [dipped [🧦 ✂️1️⃣ 🧦] 🎒]]
     [examples [[[1 2 3 [4 5 6] [* +] 💉 ▶️] [1 2 3 [26]] "Inject program into list as if it's the stack"]]]]]

[[[spec [[[program body]
             [program pred]]
            [*]]]
     [doc "The hourglass represents a conditional 'while' loop: run predicate program. If it produces logical true, run the body and repeat, otherwise stop."]
     [definition [🔳 [▶️] 🪆] ]
     [examples [[[3 [0 >] 🛡️ [🗑️ 👥 dec] ⏳ ▶️] [3 2 1 0] "While loop"]]]]]

[until [[spec [[[program body]
                [program pred]]
               [*]]]
        [definition [[🎭] 🪄 ;; reverse logic of pred
                     ;; run body once, with dummy pred result
                     👥 [[🔳] 🔀 🔗 🪄] 🪄 ⏳]]
        [examples [[[2 [even?] 🛡️ [🗑️ inc] until ▶️] [4] "Until loop"]]]]]

[times [[spec [[[integer howmany]
                [program body]]
               [program]]]
        [definition [[1️⃣ [positive?] 🛡️
                      [🗑️ dec [2️⃣ 👥 🪄] 🪄 times ▶️]
                      [🗑️] ⚖️
                      ▶️]
                     🎒]]
        [examples [[[[5] 3 times ▶️] [5 5 5] "Can create an item multiple times"]
                   [[[5] 0 times ▶️] 🔳 "0 times is a no-op"]
                   [[1 1 [inc 🔀] 3 times ▶️] [3 2] "Can run a program multiple times"]]]]]

[primrec [[spec [[[program rec1]
                  [program exit]
                  [number repetitions]]
                 [*]]]
          [definition [[▶️ ✂️1️⃣] 🎒  ;; add execute to rec1 to be recurs rec2
                       [[🗑️ ✂️1️⃣] 🎒] 🪄  ;; add drop to exit condition
                       [zero? ☯️] 🛡️ ⚓ ;; put the condition check on bottom
                       [🗑️ 👥 dec];; add the r1
                       🪆]]  ;; now its generic recur
          [examples [[[5 [1] [*] primrec ▶️] [120] "Simple countup loop"]]]]]

[bail [[spec [[program] [*]]]
       [definition [[🔳] ↔️]]
       [examples [[[🔳 [inc] bail] [🔳] "Can bail on invalid input"]
                  [[1 [inc] bail] [2] "Valid input doesn't bail"]]]]]

[bailer [[spec [[list] [*]]]
         [definition [[and] •🛡️ [📤 🪄]]]
         [examples [[[1
                      [[👥 odd?] [🗑️ inc] [👥 odd?] [🗑️ inc]]
                      bailer ▶️]
                     [2 🔳]]]]]]

1.4. Collections

[🔗 [[spec [[sized sized] [sized]]]
     [doc "The chain denotes joining two containers together"]
     [examples [[[["a" "b"] ["c" "d"] 🔗] [["a" "b" "c" "d"]] "Join two collections of strings"]
                [["ab" "cd" 🔗] ["abcd"] "Join two strings"]
                [["ab" encode "cd" encode 🔗 "abcd" encode =] [] "Two joined byte seqs are equal to the combined literal"]
                [[[[a b] [c d]] association [[e f] [a g]] 🔗] [[[a g] [c d] [e f]] association] "Joining list+assoc -> assoc, 2nd arg keys take priority"]
                [[[[e f] [a g]] [[a b] [c d]] association  🔗] [[[a b] [e f] [c d]] association] "Joining assoc+list -> assoc, 2nd arg keys take priority"]
                [[[a b c d] set [a e] 🔗] [[a b c d e] set] "Join set with list -> set"]
                [[[a e] [a b c d] set 🔗] [[a b c d e] set] "Join list with set -> set"]
                [["" "" 🔗] [""] "Join two empty strings -> empty string"]
                [["" [foo bar baz] 🔗] [[foo bar baz]] "Join empty string + list -> list (identity)"]
                [["a" [\b \c 100 101] 🔗] ["abcde"] "Join a string with a list of chars -> string"]
                [[[\b \c 100 101] "a" 🔗] ["bcdea"] "Join a list of chars with string -> string"]
                [["" [\b \c 100 101] 🔗] [[\b \c 100 101]] "Join an empty string with list of chars -> list of chars"]
                [["abc" [\d 101 "not-char" -1.1] 🔗] [[\a \b \c \d 101 "not-char" -1.1]] "Join a string with (non-char) list -> list"]
                [["abc" 🔳 🔗] ["abc"] "Join a string with empty list -> string"]
                [["" 🔳 🔗] [""] "Join empty string with empty list -> string"]
                [[[1 2 3] set [4 4 4] 🔗] [[1 2 3 4] set] "Join set with list -> set"]]]]]

[📤 [[spec [[dispenser] [item dispenser]]]
     [doc "The outbox denotes taking an item from a container."]
     [examples [[[["a" "b" "c"] 📤] [["b" "c"] "a"] "Take a string from a list"]
                [[[1 2 3] 📤] [[2 3] 1] "Take a number from a list"]
                [[[[a "foo"] [b "foo"] [c "foo"]] 📤 •🗑️ second] ["foo"] "Take an entry from association is nondeterministic"]
                [[[1 3 5 7 9] set 📤 •🗑️ odd?] [] "Take item from set is nondeterministic"]]]]]

[📮 [[spec [[item receptacle] [receptacle]]]
     [doc "The postbox denotes putting an item into a container"]
     [examples [[[🔳 1 📮] [[1]] "Put integer into empty list"]
                [[[1 2 3] 4 📮] [[1 2 3 4]] "Put integer into list"]
                [["foo" \d 📮] ["food"] "Put character into string"]
                [["foo" encode 32 📮 string] ["foo "] "Put byte into byte array"]]]]]

[📏 [[spec [[sized]
            [number]]]
     [doc "The ruler denotes getting the length of a container (number of items)"]
     [examples [[[["a" "b" "cd"] 📏] [3] "Count list of strings"]
                [["abcd" 📏] [4] "Count chars in string"]
                [["abcd" encode 📏] [4] "Count bytes in byte array"]
                [[[[a b] [c d]] association 📏] [2] "Count entries in association"]]]]]

[second [[spec [[ordered] [item]]]
         [examples [[[[4 5 6] second] [5] "Get second item of list"]
                    [["foo" second [\o]] "Get second item of string"]
                    [[🔳 second] [🔳] "Get second item of empty list -> Nothing"]]]]]

[last [[spec [[ordered] [item]]]
       [examples [[[[3 4 5 6] last] [6] "Get last item of list"]
                  [["foo" last [\o]] "Get last item of string"]
                  [[🔳 last] [🔳] "Get last item of empty list -> Nothing"]]]]]

[pop [[spec [[ordered] [item ordered]]]
      [examples [[[["a" "b" "c"] pop] [["a" "b"] "c"] "Pop last string from list"]
                 [[[1 2 3] pop] [[1 2] 3] "Pop last number from list"]]]]]

[🎁 [[spec [[item] [list]]]
     [doc "The wrapped package denotes wrapping an item in a (list) container."]
     [examples [[[1 🎁] [[1]] "Wrap a number"]
                [[[1 2] 🎁] [[[1 2]]] "Wrap a list"]]]]]

[🍫 [[spec [[list] [*]]]
     [doc "The unwrapped chocolate bar denotes unwrapping a container to place all the items inside on the stack."]
     [examples [[[[1] 🍫] [1] "Unwrap a list of one item"]
                [["foo" ["bar" "baz"] 🍫] ["foo" "bar" "baz"] "Unwrap a list of strings with existing stack items"]
                [["foo" 🔳 🍫] ["foo"] "Unwrap an empty list is a no-op"]
                [[[1 2 3] 🍫] [1 2 3] "Unwrap a list of multiple items"]]]]]

[reverse [[spec [[ordered] [ordered]]]
          [examples [[[[1 2 3] reverse] [[3 2 1]] "Reverse a list"]
                     [["123" reverse] ["321"] "Reverse a string"]
                     [[["foo" "bar" "baz"] reverse] [["baz" "bar" "foo"]] "Reverse a list of string"]]]]]

[slice [[spec [[integer integer ordered] [ordered]]]
        [examples [[["foobar" 0 3 slice] ["foo"] "Slice a string with valid indices"]
                   [["foobar" 0 7 slice] [🔳] "Slice a string with index past end -> Nothing"]
                   [["foobar" encode 0 3 slice] ["foo" encode] "Slice a byte array with valid indices"]
                   [[[a b c d e] 0 3 slice] [[a b c]] "Slice a list with valid indices"]]]]]

[cut [[spec [[integer sized] [list]]]
      [definition [[[[📏] 🛡️ 🐋 slice]
                    [0 🔀 slice]]
                   [▶️] 🚜 ▶️ 
                   [🗑️ 🗑️] 🪄 🍫]]
      [examples [[["abcdefghijklmnopqrstuvwxyz" 5 cut] ["fghijklmnopqrstuvwxyz" "abcde"] "Cut string at index"]]]]]

[empty [[spec [[sized] [sized]]]
        [examples [[["foo" empty] [""] "Create empty container from string"]
                   [["foo" encode empty] ["" encode] "Create empty container from byte array"]
                   [[[1 2 3] empty] [🔳] "Create empty container from list"]
                   [[[[a b] [c d]] association empty] [🔳 association] "Create empty container from association"]
                   [[[1 2 3] set empty] [🔳 set] "Create empty container from set"]]]]]

[range [[spec [[integer integer integer] [list]]]
        [examples [[[1 5 1 range] [[1 2 3 4]] "Create integer range with step of 1"]
                   [[3 13 3 range] [[3 6 9 12]] "Create integer range with step greater than 1"]]]]]

[empty? [[spec [[item] [boolean]]]
         [examples [[[🔳 empty?] [] "Empty list is empty"]
                    [[1 empty?] [🔳] "Number is not empty"]
                    [["" empty?] [] "Empty string is empty"]
                    [[[foo] empty?] [🔳] "Non-empty list is not empty"]]]]]

[list? [[spec [[item] [boolean]]]
        [examples [[[[1] list?] [] "A list is a list"]
                   [[🔳 list?] [] "An empty list is a list"]
                   [[5 list?] [🔳] "A number is not a list"]
                   [["foo" list?] [🔳] "A string is not a list"]
                   [[🔳 association list?] [🔳] "An empty association is not a list"]]]]]

[sort-indexed [[spec [[sized] [sized]]]
               [examples [[[[[1 1] [3 3] [2 2]] sort-indexed] [[1 2 3]] "Sorting a list of key-value pairs by key"]]]]]

[🎒 [[spec [[[list template]] [list]]]
     [doc "The backpack denotes filling a template, with items from the stack. Use 1️⃣, 2️⃣ etc for the first, second etc items from the stack. You can also splice a container item into the 'backpack', with ✂️1️⃣, ✂️2️⃣ etc. The number of stack items consumed is whatever is the highest index placeholder. So a 'backpack' of [1️⃣ 4️⃣] consumes 4 items even though 2️⃣ and 3️⃣ are not present."]
     [examples [[["x" [foo] [bar] 🍫
                  [2️⃣ [ 1️⃣ x ✂️2️⃣] c d 1 2 3] 🎒]
                 ["x" [[foo] [bar x foo] c d 1 2 3]]
                 "Packing values from the stack, into a template"]]]]]

[reduce [[spec [[[program reducer] dispenser] [item]]]
         [definition [[📤 🔀] 🪄 ;; get the first item as the initial value
                      🪜]]]]
;; DEPRECATE - this is redundant, all logical operators can take the item directly
[something? [[spec [[item] [boolean]]] 
             [definition [empty? ☯️]]
             [examples [[[1 something?] [] "A number is something"]
                        [[🔳 something?] [🔳] "Empty list is not something"]
                        [["" something?] [🔳] "Empty string is not something"]]]]]

[first [[spec [[ordered] [item]]]
        [definition [📤 •🗑️]]
        [examples [[[[4 5 6] first] [4] "Get the first item of a list"]
                   [["foo" first] [\f] "The first item of a string is the first character"]
                   [[🔳 first] [🔳] "The first item of an empty list is Nothing"]]]]]

[rest [[spec [[sized] [sized]]]
       [definition [📤 🗑️]]
       [examples [[[[1 2 3] rest] [[2 3]] "Take rest of list"]
                  [["foo" rest] ["oo"] "Take rest of string"]]]]]

[butlast [[spec [[sized] [sized]]]
          [definition [pop 🗑️]]
          [examples [[[[1 2 3] butlast] [[1 2]] "Take all but last of list"]]]]]

[prepend [[spec [[item sized]
                 [sized]]]
          [definition [🎁 🔀 🔗]]
          [examples [[[[1 2] 3 prepend] [[3 1 2]] "Prepend to list"]
                     [["oo" \f prepend] ["foo"] "Prepend to string"]]]]]

[💯 [[spec [[program sized] [program]]]
     [doc "The '100' (percent) denotes creating a consensus program from a predicate program. The returned program will check whether all the items in the container match the predicate program. Each item is placed on the stack (with remaining items hidden), and the predicate program is run. If it returns logical true, repeat with the next item, otherwise stop and return logical false."]
     [definition [•🛡️ ;; protect the rest of stack
                  [[📤 🔀 1️⃣ 🐋 👥] ;; more items
                   [🔳 ✅ 🔳] ;; empty list, return ✅
                   ↔️] 🎒
                  [🗑️ 🗑️]
                  [•🗑️]
                  [▶️] 🪆]]
     [examples [[[[2 4 6] [even?] 💯 ▶️] [] "Every number matches predicate"]
                [[[2 4 5] [even?] 💯 ▶️] [🔳] "Not every number matches predicate"]
                [[🔳 [🔳] 💯 ▶️] [] "Every item in empty list matches any predicate"]
                [[[2 4 6] 🔳 💯 ▶️] [] "Every item in list matches empty predicate"]
                [[11 [2 4 6] [+ odd?] •🛡️ 💯 ▶️] [11 ✅] "Can shield stack from predicate"]
                [[12 [[even?] [positive?] [3 mod 0 =]] [▶️] •🛡️ 💯 ▶️] [12 ✅] "Can check list of predicates with execute predicate"]]]]]

[📣 [[spec [[program sized] boolean]]
     [doc "The megaphone denotes creating a existence program from a predicate program. (The megaphone represents amplifying from a single element to the whole). The returned program will check whether any of the items in the container match the predicate program. Each item is placed on the stack (with remaining items hidden), and the predicate program is run. If it returns logical false, repeat with the next item, otherwise stop and return logical true."]
     [definition [[[📤 🔀 1️⃣ 🐋 👥 ☯️] ;; more items
                   [🔳 🔳 🔳] ;; empty list, return 🔳
                   ↔️] 🎒
                  [🗑️ 🗑️]
                  [•🗑️]
                  [▶️] 🪆]]
     [examples [[[[2 4 6] [even?] 📣 ▶️] [] "Any number matches predicate"]
                [[[3 5 7] [even?] 📣 ▶️] [🔳] "No number matches predicate"]
                [[🔳 [] 📣 ▶️] [🔳] "No item in empty list matches any predicate"]
                [[[🔳 2 4 6] 🔳 📣 ▶️] [2] "Empty predicate returns first truthy item"]
                [[11 [3 5 6] [+ odd?] •🛡️ 📣 ▶️] [11 ✅] "Stack is shielded from predicate"]
                [[-15 [[even?] [positive?] [3 mod 0 =]] [🛡️ ▶️] 📣 ▶️] [-15 ✅] "Can check list of predicates with execute predicate"]]]]]

[🎭 [[spec [[program] [program]]]
     [doc "The performing arts masks denote logically complementing a program: create a new program that returns the logical opposite of what the original program did."]
     [definition [[1️⃣ ▶️ ☯️] 🎒]]
     [examples [[[4 [odd?] 🎭 [🗑️ "even"] ["odd"] ⚖️ ▶️]
                 ["even"]]]]]]

[🚜 [[spec [[[program transform]] [program]]]
     [doc "The tractor denotes creating an item-by-item transformation. The returned program will run the transform on each item in the container on ToS. Each item is placed on the stack with remaining items hidden, and the transform program is run. Its stack effects are erased for the next item."]
     [definition [[[🔀 1️⃣ •🛡️ 🪄 🔀 📮] 🪜
                   🔳 ⚓ ;; put empty results below list
                   ▶️]
                  🎒]]
     [examples [[[[1 2 3] [inc] 🚜 ▶️] [[2 3 4]] "Pass each item through a program"]

                [[1 [1 2 3] [+] 🚜 ▶️] [1 [2 3 4]] "Program has access to rest of stack"]
                [[7 9 [1 2 3] [+ *] 🚜 ▶️] [7 9 [70 77 84]] "Stack is shielded from mapping program"]
                [[7 9 [1 2 3] [🗑️ 🗑️] 🚜 ▶️] [7 9 [7 7 7]] "Result of program can be lower stack items"]

                [[7 9 [+] 🔳 🚜 ▶️] [7 9 [+]] "Empty program is a no-op"]
                [[[+] 🚜 [7 9 [1 2 3]] 🪄 ▶️] [7 9 [10 11 12]] "Create a map program and use later"]]]]]

[🧲 [[spec [[[program predicate] sized] [list]]]
     [doc "The magnet denotes a filtering. The returned program will filter a list on ToS and leave only those items for which the predicate returns logical true."]
     [definition [🛡️ ;; run the predicate with no stack effect
                  [🗑️ 📮] [🗑️] ⚖️ ;; if match, drop the pred result and put the original item in result list
                  ;; if not, just drop the original
                  🪜 
                  [1️⃣ 🔳 ⚓ ▶️] 🎒]]  ;; place the empty result container beneath
     [examples [[[[1 2 3] [odd?] 🧲 ▶️] [[1 3]] "Filter a list with predicate"]
                [[[2 4 6] [odd?] 🧲 ▶️] [🔳] "Filter with predicate that matches no items"]
                [[33 [1 2 3] [33 + odd?] 🧲 ▶️] [33 [2]] "Filter predicate uses existing stack items"]]]]]

[sort [[spec [[program sized] [list]]]
       [definition [[👥 ✂️1️⃣ pair] 🎒
                    🚜 ▶️ sort-indexed]]
       [examples [[[[1 3 2] 🔳 sort] [[1 2 3]] "Sort a list of numbers"]
                  [[["Carol" "Alice" "bob"] 🔳 sort] [["Alice" "Bob" "Carol"]] "Sort a list of strings"]
                  [[["Charlie" "Alice" "bob"] [📏] sort] [["Bob" "Alice" "Charlie"]] "Sort list of strings by length"]]]]]

[repetition [[spec [[[integer howmany]
                     item]
                    [list]]]
             [definition [🔳 ⚓ [🎁 [📮] 🔗] 🪄 times]]
             [examples [[["hi" 3 repetition ▶️] [["hi" "hi" "hi"]] "Create a list of repeated items"]]]]]

[indexed [[spec [[list] [list]]]
          [definition [[📏] 🛡️ ▶️ 0 🔀 1 range 🔀 zip]]
          [examples [[[[a b c] indexed] [[[0 a] [1 b] [2 c]]] "Index a list"]]]]]

[indexer [[spec [🔳 [program]]]
          [definition [0 [[▶️] 🐋
                          [[pair] •🛡️ ▶️ [inc] 🪄] bail]
                       🔳 [🗑️ 🔳] [🔀] 🪆]]
          [examples [[[[a b c] [indexer collect] assemble] [[[0 a] [1 b] [2 c]]] "Index a generator"]]]]]

[indexof [[spec [[item list] [item]]]
          [definition [[[second 🎁 [1️⃣] = ☯️] skipper
                        [indexer] •🪄
                        ▶️ first] 🎒 
                       assemble]]
          [examples [[[[a b c] [c] 🍫 indexof] [2] "Get the index of first matching item"]
                     [[[a b c] [d] 🍫 indexof] [🔳] "No matching item -> Nothing"]
                     [[[a b c d c e] [c] 🍫 indexof] [2] "Multiple matches returns index of first match"]]]]]

[interpose [[spec [[item ordered] [ordered]]]
            [definition [🔳 flip
                         [🔀 pair 🔗 [pop] 🛡️] 🪜
                         🗑️ pop 🗑️]]
            [examples [[[[foo bar baz] "hi" interpose] [[foo "hi" bar "hi" baz]] "Interpose string between words"]
                       [[🔳 "hi" interpose] [🔳] "Empty list is a no-op"]
                       [[[foo] "hi" interpose] [[foo]] "Single item list is a no-op"]]]]]

[starts? [[spec [[[ordered prefix] [ordered target]] [boolean]]]
          [definition [[[zip [🍫 =] 💯 ▶️] ;; the items at matching indexes are equal
                        [[📏] both >=]] ;; the prefix is shorter than the target
                       [▶️] •🛡️ 💯 ▶️
                       •🗑️ •🗑️]] ;; drop the originals
          [examples [[["abcd" "ab" starts?] [] "String starts with matching string"]
                     [["abcd" "" starts?] [] "String starts with empty string"]
                     [["" "ab" starts?] [🔳] "Empty string doesn't start with a string"]
                     [["abcd" "bb" starts?] [🔳] "String doesn't start with non-matching string"]
                     [[[1 2 3 4] [1 2] starts?] [] "List starts with matching list"]]]]]

[ends? [[spec [[ordered ordered] [boolean]]]
        [definition [[reverse] both starts?]]
        [examples [[["abcd" "cd" ends?] [] "String ends with matching string"]
                   [["abcd" "" ends?] [] "String ends with empty string"]
                   [["abcd" "bb" ends?] [🔳] "String doesn't end with non-matching string"]
                   [[[1 2 3 4] [3 4] ends?] [] "List ends with matching list"]]]]]

[pair [[spec [[item item] [list]]]
       [definition [[🎁] 🪄 📮]]
       [examples [[[1 2 pair] [[1 2]] "Pair up two numbers into a list"]
                  [[["hi"] ["there" "foo"] pair] [[["hi"] ["there" "foo"]]] "Pair up two lists into a new list"]]]]]

[pair? [[spec [[item] [boolean]]]
        [definition [[📏 2 =]
                     [[asked] 🔍 [sized?] =]
                     [🗑️ 🗑️ 🔳]
                     [🔳] ⚖️ 🩹 ▶️] ]
        [examples [[["ab" pair?] [] "2-character string is a pair"]
                   [[[a b] pair?] [] "2-item list is a pair"]
                   [["abc" pair?] [🔳] "3-character string is not a pair"]
                   [[🔳 pair?] [🔳] "Nothing is not a pair"]
                   [[7 pair?] [🔳] "Number is not a pair"]]]]]

[triplet [[spec [[item item] [list]]]
          [definition [[pair] 🪄 📮]]
          [examples [[[1 2 3 triplet] [[1 2 3]] "Make a 3-item list from 3 stack items"]
                     [[["hi"] ["there" "foo"] ["bar"] triplet] [[["hi"] ["there" "foo"] ["bar"]]] "Make a 3-item list from smaller lists"]]]]]

[both? [[spec [[program item item] [boolean]]]
        [definition [⚓ pair 🔀 💯 ▶️]]
        [examples [[[1 2 [odd?] both?] [🔳] "Test two items for predicate when not all match"]
                   [[1 3 [odd?] both?] [] "Test two items for predicate when all match"]]]]]

[both [[spec [[program [item a] [item b]] [item item]]]
       [definition [[pair] 🪄 🪜 ▶️]]
       [examples [[[1 2 [inc] both] [2 3] "Run program on two stack items"]]]]]

[walk [[spec [[[program item-transform] list] [list]]]
       [definition [[✂️1️⃣] 🎒 ;; the negative branch
                    [list?] 🛡️ ;; pred
                    [🗑️ 🔳 🔀] 🛟 ;; affirmative branch
                    [[✂️1️⃣ 🔗] 🎒 🪜 ▶️ 🎁] ;; recur into each subitem and wrap
                    🪆 [✂️1️⃣ 🍫] 🎒]] ;; unwrap at the end
       [examples [[[[1 2 [3 [4 5] 6]] [inc 🎁] walk ▶️] [[2 3 [4 [5 6] 7]]] "Walk a nested list"]
                  [[[1 2 [3 [4 5] 6]] [👥 inc pair] walk ▶️] [[1 2 2 3 [3 4 [4 5 5 6] 6 7]]] "Walk a nested list and splice results"]]]]]

[flatten [[spec [[list] [list]]]
          [definition [🔳 🔀 [list?] 🛡️ [🗑️ ] [📮] [🪜 ▶️] 🪆 ▶️]]
          [examples [[[[a b [c [d e] f] g] flatten] [[a b c d e f g]] "Flatten a nested list"]]]]]

[pad [[spec [[[item padding] [integer newsize] sized] [sized]]]
      [definition [[[[📏] 🛡️ ▶️] 🐋 -] 🪄
                   🔀 repetition ▶️ 
                   🔀 🔗]]
      [examples [[[[1 2 3] 5 0 pad] [[0 0 1 2 3]] "Pad a list at front, to given size"]
                 [[[1 2 3 4 5 6] 5 0 pad] [[1 2 3 4 5 6]] "Padding a list to smaller than original size is a no-op"]]]]]

1.4.1. Associations

[get [[spec [[item sized] [item]]]
      [examples [[[[[a 3] [c 2]] [a] 🍫 get] [3] "Get a key from an association"]
                 [[[10 11 12 13] 1 get] [11] "Get an item by index from a list"]
                 [["foobar" 3 get] [\b] "Get a character by index from a string"]
                 [["foobar" encode 3 get] [98] "Get an integer by index from a byte array"]
                 [[[[a 3] [c 2]] [b] 🍫 get] [🔳] "Get a nonexistent key -> Nothing"]]]]]

[assign [[spec [[[item value]
                 [list keys]
                 sized]
                [association]]]
         [examples [[[[[a b] [c d]] [a] 5 assign]
                     [[[a 5] [c d]] association] "Assign a new value to an existing key"]

                    [[[[a b] [c d]] [e] 5 assign]
                     [[[a b] [c d] [e 5]] association] "Assign a new value to a new key"]

                    [[[[a b] [c [[d e]]]] [c d] 5 assign]
                     [[[a b] [c 🔳]] [c] [[d 5]] association assign] "Assign a new nested key, promoting to nested association"]

                    [[[[a b] [c [[d e]]]] [1 1 0] 5 assign]
                     [[[a b] [c [5]]]] "Assign a new index in a nested list"]

                    [[[1 2 3] [1 0 0] "foo" assign]
                     [[1 [["foo"]] 3]] "Assign a new index in a nested list"]

                    [[[[a [1 2 3]]] [a 0] 10 assign]
                     [[[a [10 2 3]]] association] "Assign a nested key in a mixed structure of association and list"]

                    [[[1 2 3] [1 2] "foo" assign]
                     [[1 [🔳 🔳 "foo"] 3]] "Assign an index creating placeholders for missing list items"]]]]]

[unassign [[spec [[[item key] [sized into-association]] [association]]]
           [examples [[[[[a b] [c d]] [a] unassign]
                       [[[c d]] association] "Unassign a key from an association, promoting from list"]

                      [[[[a b] [c d]] [e] unassign]
                       [[[a b] [c d]] association] "Unassign a key that doesn't exist, only promotes"]

                      [[[[a b] [c d]] [e f] unassign]
                       [[[a b] [c d]] association] "Unassign multiple keys that don't exist only promotes"]

                      [[[[a b] [c [[d e] [f g]]]] [c x] unassign]
                       [[[a b]] [c] [[d e] [f g]] association assign] "Unassign multiple keys where last doesn't exist, only promotes"]

                      [[[[a [[b c] [d e]]]] [a d] unassign]
                       [🔳 association [a b] [c] 🍫 assign] "Unassign associative keylist from nested structure, promoted to association"]

                      [[[0 1 2 [[a b] [c d]]] [3 c] unassign]
                       [[0 1 2] [[a b]] association 📮] "Unassign mixed keylist from nested structure, inner only is promoted to association"]]]]]

[association? [[spec [[item] [boolean]]]
               [examples [[[[[a b] [c d]] association association?] [] "Association is an association"]
                          [[[[a b] [c d]] association?] [🔳] "A list is not an association, even if it's possible to promote"]
                          [[1 association?] [🔳] "A number is not an association"]
                          [[🔳 association?] [🔳] "An empty list is not an association"]
                          [[🔳 association association?] [] "An empty association is an association"]
                          [[🔳 [a] 1 assign association?] [] "A list promoted to association by assignment, is an association"]]]]]

[association [[spec [[item] [association]]]
              [examples [[[[[a b] [c d]] association
                           [[c d] [a b]] association =]
                          [] "A list can be promoted to association"]

                         [[[[a b] [c d]]
                           [[c d] [a b]] association =]
                          [🔳] "An association and list are not the same, even if keys/vals are the same"]

                         [[[[a b] [c d]]
                           [[a b] [c d]] association =] [🔳] "An association is not the same as the list it was promoted from"]]]]]
;; Associative words
[update [[spec [[program [list keys] [sized into-association]]
                [association]]]
         [definition [•🛡️
                      [🔍] 🛡️ 🪄
                      ▶️ assign]]
         [examples [[[[[a 1] [b 2]] [b] [inc] update]
                     [[[a 1] [b 3]] association] "Update a value in an association"]

                    [[[[a [[c 3] [d 5]]] [b 2]]
                      [a c] [inc] update
                      [a c] 🔍]
                     [4] "Update a value in a nested association"]

                    [[[[a [1 3 5 7]] [b 2]]
                      [a 2] [inc] update]
                     [[[a [1 3 6 7]] [b 2]] association] "Update a value in a mixed association/list structure"]

                    [["hi"
                      [[a [[c 3] [d 5]]] [b 2]]
                      [a c] [🗑️ 🗑️ 10 15] update
                      [a c] 🔍]
                     ["hi" 15] "Update function can't destroy stack items"]

                    [[[[a 1] [b 2]] [d] [5] update]
                     [[[a 1] [b 2] [d 5]] association] "Update creates new key when it doesn't exist"]

                    [[[[a [[c 3] [d 5]]] [b 2]]
                      [a e] [5 6 +] update
                      [a e] 🔍]
                     [11] "Update function can ignore previous value"]]]]]

[🔍 [[spec [[[list keys] sized] [item]]]
         [definition [🔳 ;; keylist not empty
                      [📤 🔀 [get] 🪄] ;; extract the first key and 🔍
                      ⏳ ▶️]]
         [examples [[[[[a b] [c d]] association [a] 🔍] [[b] 🍫] "Lookup the value of a key in an association"]
                    [[[[a b] [c d]] [a] 🔍] [[b] 🍫] "Lookup the value of a key, promoting a list to association"]
                    [[[[a b] [c d]] [e] 🔍] [🔳] "Looking up a key that doesn't exist returns Nothing"]
                    [[[[outer [[a b] [c d]]]] [outer c] 🔍] [[d] 🍫] "Lookup in a nested structure, with promotion"]]]]]

;; TODO: fix the case where you just want a value [[type foo]] - only
;; one item but you want the value, not key
[type [[spec [[item] [item]]]
       [definition [[[[empty?] [[nothing]]]
                     [[word?] [[word]]]
                     [[number?] [[number]]]
                     [[string?] [[string]]]
                     [[bytes?] [[bytes]]]
                     [[pipe?] [[pipe]]]
                     [[error?] [[error]]]
                     [[environment?] [[environment]]]
                     [[set?] [[set]]]
                     [[association?] [🗑️ [[[📏 1 =] [🗑️
                                                    [first first [type] 🍫 =] 🛡️
                                                    [🗑️ first second]
                                                    [first first]
                                                    ⚖️ ▶️]]
                                         [[[type] 🔍] [•🗑️]]
                                         [[] [[association] 🍫 •🗑️ •🗑️ dump]]] decide
                                      🎁 🔳 🔳 🛟]]
                     [[list?] [[list]]]
                     [[] [[item]]]]
                    decide 🍫 •🗑️ •🗑️]]
       [examples [[[[[foo 1]] association type] [[foo] 🍫] "An association with one key assumes it is its type"]
                  [[1 type] [[number] 🍫] "Integers are of type number"]
                  [[1.0 type] [[number] 🍫] "Floats are of type number"]
                  [[🔳 type] [[nothing] 🍫] "Empty list is of type nothing"]
                  [["foo" encode type] [[bytes] 🍫] "A byte array is of type bytes"]
                  [["foo" type] [[string] 🍫] "A string is of type string"]
                  [[[1 2 3] set type] [[set] 🍫] "A set is of type set"]
                  [[🔳 environment type] [[environment] 🍫] "An environment is of type environment"]
                  [[[[type foo]] association type] [[foo] 🍫] "An association with a single type key, the value is its type"]
                  [[[[type foo] [attr "blah"]] association type] [[foo] 🍫] "An association with a single type key, the value is its type"]
                  [[[[attr1 foo] [attr2 "blah"]] association type] [[association] 🍫] "An association with multiple keys and no type key, is of type association"]
                  [[[[type url] [value "http://foo.com"]] association type] [[url] 🍫] "An association with type/value keys, uses the type key for its type"]]]]]

[value [[spec [[[sized into-association]] [item]]]
        [definition [[📏 1 =] 🛡️ ;; if it's a single item
                     [🗑️ first second] ;; the value is the value of that first item
                     [[value] 🔍] ;; otherwise look up the key 'value'
                     ⚖️ ▶️]]
        [examples [[[[[foo 1]] value] [1] "The value of a single-entry association is the value of the key-value pair"]

                   [[[[type url] [value "http://foo.com"]] value]
                    ["http://foo.com"] "The value of an object is the value key"]]]]]

[zip [[spec [[[dispenser values] [dispenser keys]] [list]]]
      [definition [🔳 ⚓ ;; save accumulator below args
                   [🔳 both?] 🛡️ ;; stop when either list is empty
                   [🗑️ [📤] both •🔀 pair ;; take from each list and pair them up[📮] •🪄] ;; put them into the accumulator
                   ⏳ ▶️
                   🗑️ 🗑️]] ;; drop the empty containers
      [examples [[[[a b c] [1 2 3] zip] [[[a 1] [b 2] [c 3]]] "Zip two lists together into a single list of pairs"]
                 [[[a b c d] [1 2 3] zip] [[[a 1] [b 2] [c 3]]] "Zip two lists of unequal size pads with Nothing values"]]]]]

[label [[spec [[[sized labels]] [association]]]
        [definition [🔳 🔀 ;; labels acc
                     [🎁 🛟 assign] 🪜 ▶️]]
        [examples [[["Alice" 23 "123 Main St" [address age name] label]
                    [[[address "123 Main St"]
                      [age 23]
                      [name "Alice"]] association]
                    "Label values on the stack as an association"]]]]]

1.4.2. Sets

;; TODO add 'set' type for spec?
[set [[spec [[item] [item]]]
      [examples [[[[1 2 3 1 2 3] set] [[1 2 3] set] "Promote a list to a set"]
                 [["hello" set] ["helo" set] "Promote a string to a set"]]]]]

[set? [[spec [[item] [boolean]]]
       [examples [[[[1 2 3] set set?] [] "A set is a set"]
                  [[[1 2 3] set?] [🔳] "A list is not a set"]]]]]

[contains? [[spec [[item [item container]] [boolean]]]
            [examples [[[[1 2 3] 3 contains?] [] "List contains a number"]
                       [[[1 2 3 3 5] set 3 contains?] [] "A set contains a number"]
                       [[[1 2 3] 4 contains?] [🔳] "A list doesn't contain a number"]
                       [[5 3 contains?] [🔳] "A number is atomic and doesn't contain anything"]
                       [[[foo] 🍫 \o contains?] [🔳] "A word is atomic and doesn't contain anything"]
                       [["food" "foo" contains?] [] "A string contains a sub-string"]
                       [[[a b c d] [b c] contains?] [🔳] "A list doesn't contain a sub-list (due to ambiguity with what 'contains' means with lists)"]
                       [[[a [b c] d] [b c] contains?] [] "A list contains another list"]
                       [[[a [b c] d] set [b c] contains?] [] "A set contains a list"]
                       [["food" \o contains?] [] "A string contains a character"]]]]]

[intersection [[spec [[sized sized] [sized]]]
               [examples [[[[1 2 3] [2 3 4] intersection] [[2 3] set] "Intersection of two lists expressed as set"]]]]]

1.4.3. Generators

;; infinite sequence (generators) functions

[[generator [[spec [program program]]
             [definition [🔳 [🔳] [🔀] 🪆]]]]

 [liberator [[spec [🔳 [program]]]
             [definition [[📤] generator]]]]

 [reap [[spec [[[program generator]] [item]]]
          [description "Generates a value from a wrapped generator (stacked generator inside a list)"]
          [definition [🔳 🔀 💉 ▶️ first]] ;; the now-empty dispenser
          [examples [[[[integers generator 5 taker collect] reap] [[0 1 2 3 4]]]]]]]

 [assemble [[spec [[program dispenser] [list]]]
            [definition [[liberator ✂️1️⃣] 🎒
                         [🎁] 🪄 💉 ▶️ first]]
            [examples [[[[1 2 3 4 5]
                         [[odd?] keep
                          collect] assemble]
                        [[1 3 5]]]]]]]

 [produce [[spec [[[list wrapped-generator]] [list item]]]
           [definition [[▶️] 💉 ▶️ 📤]]
           [examples [[[integers generator
                        [👥 *] each
                        10 dropper
                        🔳 🧦 
                        produce •🗑️] [100]]]]]]

 [🧹 [[spec [[sized program] [program]]]
      [doc "The broom denotes a gathering - the returned program will repeatedly call the given program to generate items, and put them into the container below it."]
      [definition [[[▶️] 🐋] [📮]]]
      [examples [[[[\a \b \c \d] liberator "" 🧹 ▶️]
                  [🔳 "abcd"] "Sweep into an empty string"]
                 [[0 10 1 range liberator
                   5 dropper
                   [10 *] each
                   🔳 🧹 ▶️]
                  [🔳 [50 60 70 80 90]] "Generate a sequence and put it into the given container"]]]]]

 [collect [[spec [[program] [list]]]
           [definition [🔳 🧹 ▶️]]
           [examples [[[[[1 2 3 4] liberator collect] 🛡️ ▶️]
                       [[1 2 3 4]]]
                      [[[0 10 1 range liberator
                         5 dropper
                         [10 *] each
                         collect]
                        🛡️ ▶️]
                       [[50 60 70 80 90]] "Collect from a generator into an empty list"]]]]]

 [each [[spec [[program] [program]]]
        [definition [•🛡️ ;; prevent mapping program from overwriting stack
                     [▶️ 1️⃣ bail] 🎒 ;; only execute the mapping program if parent produces value
                     🔳 [🔳] [🔀] 🪆]] 
        [examples [[[[1 2 3 4] liberator
                     [👥 *] each
                     collect]

                    [🔳 [1 4 9 16]] "Generate a sequence transforming each value"]]]]]

 [joiner [[spec [🔳 [program]]]
          [definition [[[reason "Deprecated, see 'expected' for what to use instead"]
                        [expected [[🔗] fold]]] fail]]
          [examples [[[[[1 2 3] [4 5 6] [7 8 9]]
                       [joiner]
                       assemble]

                      [[[1 2 3 4 5 6 7 8 9]]]]]]]]

 [taker [[spec [[[integer howmany]] [program]]]
         [definition [[positive?] 🛡️ ;; counter still positive?
                      [🗑️ [▶️] 🐋 ;; run the parent generator
                       🔳 [🔳 🔳] ↔️] ;; add padding to drop later
                      [🔳] ⚖️ ;; otherwise return nothing
                      [[dec] 🪄] ;; decrement counter
                      [🗑️ 🔳] ;; discard the counter but keep parent, all done
                      [🔀] 🪆]]
         [examples [[[[1 2 3 4 5] [3 taker collect] assemble]
                     [[1 2 3]] "Taker takes given number of items from the parent"]

                    [[[1 2 3 4 5] [6 taker collect] assemble]
                     [[1 2 3 4 5]] "Taker stops when parent ends before given number of items"]

                    [[[1 2 3 4 5 6] liberator
                      3 taker collect
                      [2 taker collect] 🐋
                      pair restore] ;; just keep the top 2 items
                     [[4 5] [1 2 3]] "Taker leaves parent intact so it can be reused"]]]]]

 [catcher [[spec [🔳 [program]]]
           [definition [[[▶️] 🐋 ;; get value from parent
                         [🔀 [▶️] 🛡️ ▶️] bail ;; only check pred iff we get a value, preserve pred
                         🔳
                         [🔳 🔳 🔳] ↔️] ;; place some dummy values to drop if we didn't get a value
                        [🗑️ 🔀] ;; iff pred matches drop the pred result 
                        [🗑️ 🗑️ 🗑️ 🔳] ;; otherwise drop all the stuff we no longer need
                        ⚖️ 🔳
                        [[🔳] 🔳] [🔀] 🪆]]
           [examples [[[[1 2 3 -4 5]
                        [[positive?] catcher collect]
                        assemble]

                       [[1 2 3]]]

                      [[[1 2 3 4 5]
                        [[positive?] catcher collect]
                        assemble]

                       [[1 2 3 4 5]]]]]]]

 [dropper [[spec [🔳 [program]]]
           [definition [[positive?] 🛡️ ;; condition
                        [🗑️ [▶️] 🐋 ;; call parent 
                         🔳 ;; if we get something, we're done
                         [🗑️ 🔳 🔳] ;; otherwise signal stop with empty generator
                         ↔️]
                        [🗑️ ▶️ 🔳] ⚖️ ;; if counter reaches zero we're done dropping 
                        [🗑️ dec] ⏳
                        🔳 [🔳] [🗑️] 🪆]]
           [examples [[[[1 2 3 4 5] [3 dropper collect]
                        assemble]
                       [[4 5]]]
                      [[[1 2 3 4 5] [6 dropper collect]
                        assemble]
                       [🔳]]]]]]

 [skipper [[spec [🔳 [program]]]
           [definition [[[▶️] 🐋] ;; get the item from parent
                        [🔀 [▶️] 🛡️ ▶️] ;; run the pred on it, keep the pred
                        [🗑️ 🔳 🔳] ⚖️ ;; when parent is empty, leave negative on the stack
                        [🗑️ •🗑️];; keep consuming items while they match pred
                        🔳 [🔳] [🗑️ 🗑️] 🪆]]
           [examples [[[[1 2 -3 4 5]
                        [[positive?] skipper collect]
                        assemble]

                       [[-3 4 5]]]]]]]

 [keep [[spec [[program] [program]]]
        [definition [[▶️  ;; exec the generator below to get value v
                      [1️⃣ 🛡️ ▶️ ☯️] ;; check if v does NOT match given pred, 
                      [🔳 🔳] ;; if generator below is finished, return 2 empty values 
                      ↔️] 🎒
                     [🗑️ 🗑️] ;; drop both the value v and the result of pred;; repeat until generator below is finished
                     🔳 [🔳] [🔀] 🪆]]
        [examples [[[[1 2 3 4 5] liberator
                     [odd?] keep
                     collect]

                    [🔳 [1 3 5]]]]]]]

 [group [[spec [[[program group-by]] [association]]]
         [definition [🛡️
                      [1️⃣ ▶️ ;; k v state
                       🎁 🔀   ;;  v k state
                       🎁 [📮] 🔗 update] 🎒
                      🔳 association ;; state f
                      🔀 cram]]
         [examples [[[[1 2 3 4] liberator [odd?] group]
                     [🔳 [[[1 3]] [🔳 [2 4]]] association]]]]]]

 [splitter [[spec [[sized] [program sized sized]]]
            [definition [[[👥 [📮 1️⃣] 🪄  ;; add new value to input buffer
                           [☯️] ;; the input was empty
                           [ends?] 🛡️ ;; the input buffer ends in the delimiter
                           pair ;; user both these as conditions
                           [▶️] 📣 
                           [🗑️ ;; the bool
                            📏 ;; the delim 
                            0 🔀 - 0 🔀 slice] ;; chop the length of the divider 
                           [🗑️ 🔳]
                           ⚖️ ▶️] 🪄 ;; under the output
                          🔀 ;; put possible new output on top
                          [👥 empty [📮] 🪄 🔀] 🔳 ↔️]
                         over empty ;; starting empty container for parse
                         [🎒] 🪄]]
            [examples [[["abcabc" ["b" splitter parse collect] assemble]
                        [["a" "ca" "c"]]]
                       [[[1 2 3 4 2 5] [[2] splitter parse collect] assemble]
                        [[[1] [3 4] [5]]]]]]]]

 [parse [[spec [[[program partial-parser] [[program parser]]]]]

         [doc "A stream parser. On the stack should be: 1) an input
               buffer that receives chunks of input from upstream
               (usually an empty string or byte array or list
               depending on what type of data is being produced), 2)
               program that takes 3 args: parsed object output buffer
               (on top), a new input item, and an unparsed input
               buffer. The function should return new input and
               output buffers. If there is enough input to create a
               new output, the program should do so, otherwise it only
               needs to combine the new input with the existing input
               buffer. An empty input should signal an end-of-stream
               condition and it's up to the program how to interpret
               that."]

         [definition [🔳 ;; state - parsed object output buffer (on top), unparsed input 
                      🔳 ;; there's output?
                      [🔳]  ;; leave an empty value to be consumed by outer ⏳ exiting
                      [🔳 [▶️] ••🐋] ;; exec parent generator 
                      ⚖️ 
                      [🔀 [👥] ••🐋 ▶️] ;; exec a copy of parser program: output input parser[📤] [[🔳] 🔀] ;; leave empty generator if we hit end of stream
                      [🔀] 🪆]]
         [examples [[[[[[104 101 108 108 111]              ;; "hello" (all ASCII)
                        [228 189 160 229 165 189]          ;; "你好" (two complete Chinese chars)
                        [104 105 226]                      ;; "hi" + start of "€"
                        [130 172]                          ;; completion of "€"
                        [240 159 145]                      ;; start of "👑"
                        [145]                              ;; completion of "👑"
                        [97 98 99 240]                     ;; "abc" + start of "🌈"
                        [159 140 136]]                     ;; completion of "🌈"

                       liberator
                       [#b64 "" 🔀 [📮] 🪜 ▶️] each ;; convert lists of ints to byte arrays
                       [parse-utf8] #b64 ""
                       parse "" 🧹 ▶️] reap]
                     ["hello你好hi€👑abc🌈"]]

                    [[[["[foo] [bar] [ba"
                        "z] [quux"
                        "] [[this] "
                        "[that]]"
                        "[foo" "]"] liberator
                       [parse-edn] "" parse collect]
                      reap]
                     [[[foo] [bar] [baz] [quux] [[this] [that]]
                       [foo]]]]]]]]

 [combinations [[spec [🔳 [program]]]
                [definition [[📏] 🛡️ -1 ;; l idx i
                             [[[🔀 📏 =] 🐋] [🗑️ 🗑️ 📤 0 🔀] when
                              [[🎁 🔍] 🐋 [pair] bail] 🛡️ [inc] •🪄]]]
                [examples [[[[1 2 3] [combinations] assemble] [[[1 2] [1 3] [2 3]]]]]]]]

 [frequencies [[spec [🔳 [association]]]
               [definition [🔳 association
                            [🎁 [🔳 [inc] [1] ⚖️ ▶️ ] update]
                            cram]]
               [examples [[["Hello there!" [frequencies] assemble]
                           [[[\space 1]
                             [\! 1]
                             [\H 1]
                             [\e 3]
                             [\h 1]
                             [\l 2]
                             [\o 1]
                             [\r 1]
                             [\t 1]] association]]]]]]

 [fold [[spec [[[program reducing-function] [program generator]] [item]]]
        [definition [[▶️] 🪄 ;; generate the first item below the reducer
                     cram]]
        [examples [[[[integers generator
                      1 dropper
                      10 taker
                      [+] fold] reap] [55]]]]]]

 [cram [[spec [[[program reducing-function]
                [item initial-value]
                [program generator]] [item]]]
        [definition [[[▶️] •🐋] ;; check that we generated another item
                     [🔀 [▶️] 🛡️ ▶️ ⚓ •🗑️ ••🗑️] ;; if so, run the reducer shielded and drop component items
                     🔳 ;; otherwise stop
                     [▶️] 🪆
                     ▶️ 🗑️]]
        [examples [[[[integers generator
                      1 dropper
                      10 taker
                      0 [+] cram]
                     reap] [55]]]]]]

 [integers [[spec [🔳 [program]]]
            [definition [-1 [inc 👥]]]]]

 [partition [[spec [[[number partition-size] [program generator]] [program]]]
             [definition [[flip [📏] 🛡️ ▶️ 1️⃣ >=] 🎒
                          [🗑️ •🔀 📮 [🎁] 🪄]
                          [🔀 📮 🔀]
                          ⚖️ 🔳 parse]]
             [examples [[[[1 2 3 4 5 6 7] [2 partition collect] assemble]
                         [[[1 2] [3 4] [5 6] [7]]]]]]]]]
🔗

1.5. Dictionary modules

[dictionary [[spec [🔳 [list]]]]]

[cache [[spec [[item bytes] [bytes]]]]]

[decache [[spec [[item] [bytes]]]]]

[hashbytes [[spec [[bytes] [bytes]]]
            [examples [[[["foo" encode hashbytes] 2 times ▶️ =] []]
                       [["foo" encode hashbytes
                         "fop" encode hashbytes
                         =]
                        [🔳]]]]]]

[resolve [[spec [[word] [word]]]
          [examples [[[[+] 🍫 resolve] [[core/+] 🍫]]]]]]

[namespace [[spec [[bytes word] [word]]]
            [examples [[[[foo] 🍫 #b64 "quux" namespace] [[quux/foo] 🍫]]]]]]

[unnamespace [[spec [[word] [bytes word]]]
              [examples [[[[quux/foo] 🍫 unnamespace] [[foo #b64 "quux"] 🍫]]]]]]

[dictmerge [[spec [[[dictionary module] [dictionary original] [bytes hash]] [dictionary]]]]]
[updates [[spec [[[sized word-updates]] [[program single-update]]]]
          [definition [[[📤]
                        [[0] [🎁] update ;; wrap the word name to get a path to update
                         [update] 🔗] each
                        joiner generate] •🛡️]]]]

[entry [[spec [[[program definition]] [[association full-entry]]]]
        [definition [[definition] label]]]]

[words [[spec [🔳 [association]]]
        [definition [dictionary [words] 🔍]]]]

[lingo [[spec [🔳 [association]]]
        [definition [dictionary [lingo] 🔍]]]]

[module [[spec [[[item wrapped-module-alias-or-hash]] [program]]]
         [doc "reads a cached module from disk and puts it on the stack as a program"]
         [definition [decache string read]]
         [examples [
          [["123" encode [crypto] stdmod [hash] confine]
           [#b64 "_1vRbfFezlcTCUfQCjC1FKukWLoOAeBuvxNXUDbFKSk"]]]]]]

[inscribe [[spec [[[bytes raw-module] dictionary] [dictionary]]]
           [definition [[[hashbytes] ;; calculate module hash
                         [string read [words] 🔀 update]] ;; install the module in the dictionary
                        [▶️] 🚜 ▶️ ;; fork 
                        •🗑️ 🍫 •🔀 dictmerge]]]]

[draft [[spec [[[sized definitions]] [[program dictionary-updater]]]]
        [definition [[[1] [entry] update] 🚜 ▶️ ;; create full entries for each definition
                    [1️⃣ 🔗] 🎒]]]]  ;; add 'join' to join the entries with the existing dictionary

[let [[spec [[program [sized entries]] [*]]]
      [definition [[draft dictionary 🔀 [emit encode hashbytes] 🛡️ ▶️ 
                    [[[words] 🔀 update] 🛡️ ▶️ •🗑️] 🪄
                    ⚓ [dictmerge] ••🛡️ ▶️] 🪄
                   🛟 🎁 [📮] 🔗
                   •🔀 [modules] 🔀 update
                   [dictionary program] label environment
                   ;; TODO try using confine here
                   [1️⃣ capture evaluate [stack] 🔍 restore] 🎒]] 
      [examples [[[[[times5 [5 *]]
                    [doubledec [dec dec]]]
                   [3 times5 doubledec] let ▶️] [13]]
                 [[[[🔀 [5]]]
                   ["a" "b" "c" 🔀]
                   let ▶️]
                  ["a" "b" "c" 5]]
                 [[[[foo ["outer"]]]
                   ["inner"] let
                   [foo] label
                   [foo] let ▶️] ["inner"]]]]]]

[definition [[spec [[list] [program]]]
             [definition [[lingo ✂️1️⃣ definition] 🎒 dictionary 🔀 🔍]]
             [examples [[[1 2 3 [🔀] definition ▶️] [1 3 2] "Fetch the definition of a builtin word and use it"]
                        [[1 2 3 [flip] definition ▶️] [3 2 1] "Fetch the definition of a word and use it"]]]]]

1.6. Math

[+ [[spec [[number number] [number]]]
    [examples [[[1 2 +] [3]]
               [[1.1 2.2 + 3.3 0.001 within?] []]
               [[1 2.2 +] [3.2]]]]]]

[- [[spec [[number number] [number]]]
    [examples [[[2 1 -] [1]]
               [[1.1 2.2 - -1.1 0.00001 within?] []]
               [[2.2 1 - 1.2 0.00001 within?] []]]]]]

[* [[spec [[number number] [number]]]
    [examples [[[4 3 *] [12]]
               [[10 1.5 * 15 0.0001 within?] []]
               [[5 0 *] [0]]
               [[5 -1 *] [-5]]]]]]

[/ [[spec [[number number] [number]]]
    [examples [[[12 3 /] [4]]
               [[15 1.5 /] [10.0]]
               [[0 1 /] [0]]
               [[1 0 / handle [reason] 🔍] [1 0 "division by zero"]]]]]]

[quot [[spec [[number number] [number]]]
       [examples [[[16 5 quot] [3]]]]]]

[rem [[spec [[number number] [number]]]
      [examples [[[17 5 rem] [2]]]]]]

[mod [[spec [[number number] [number]]]
      [examples [[[17 5 mod] [2]]]]]]

[exp [[spec [[number number] [number]]]
      [examples [[[2 5 exp] [32]]
                 [[2 2.5 exp 5.656854 0.00001 within?] []]]]]]

[log [[spec [[number number] [number]]]
      [examples [[[32 2 log] [5]]]]]]

[floor [[spec [[number] [number]]]
        [examples [[[2.1 floor] [2]]]]]]

[ceiling [[spec [[number] [number]]]
          [examples [[[2.1 ceiling] [3]]]]]]

[round [[spec [[number] [number]]]
        [examples [[[2.1 round] [2]]]]]]

[sqrt [[spec [[number] [number]]]
       [examples [[[9 sqrt] [3]]
                  [[81 sqrt] [9]]]]]]

[inc [[spec [[number] [number]]]
      [examples [[[1 inc] [2]]
                 [[-1 inc] [0]]
                 [[99 inc] [100]]]]]]

[dec [[spec [[number] [number]]]
      [examples [[[2 dec] [1]]
                 [[0 dec] [-1]]
                 [[100 dec] [99]]]]]]

[abs [[spec [[number] [integer]]]
      [examples [[[2.1 abs] [2.1]]
                 [[-0.2 abs] [0.2]]
                 [[-2 abs] [2]]
                 [[0 abs] [0]]]]]]

[odd? [[spec [[number] [boolean]]]
       [examples [[[1 odd?] []]
                  [[-1 odd?] []]
                  [[4 odd?] [🔳]]]]]]

[even? [[spec [[number] [boolean]]]
        [examples [[[2 even?] []]
                   [[-2 even?] []]
                   [[3 even?] [🔳]]]]]]

[zero? [[spec [[number] [boolean]]]
        [examples [[[0 zero?] []]
                   [[0.0 zero?] []]
                   [[-0.00001 zero?] [🔳]]
                   [[1.1 zero?] [🔳]]]]]]

[number? [[spec [[item] [boolean]]]
          [examples [[[[1] number?] [🔳]]
                     [[🔳 number?] [🔳]]
                     [[5 number?] []]
                     [[5.01 number?] []]]]]]

[integer? [[spec [[item] [boolean]]]
          [examples [[[[1] integer?] [🔳]]
                     [[🔳 integer?] [🔳]]
                     [[5 integer?] []]
                     [[-5 integer?] []]
                     [[0 integer?] []]
                     [[5.01 integer?] [🔳]]
                     [[5.00 integer?] [🔳]]]]]]
[number [[spec [[item] [number]]]
         [examples [[["12" number] [12]]
                    [["-11.1" number] [-11.1]]
                    [["a" first number] [97]]]]]]
[positive? [[spec [[number] [boolean]]]
            [definition [0 >]]]]

[negative? [[spec [[number] [boolean]]]
            [definition [0 <]]]]

[within? [[spec [[number number] [boolean]]]
          [definition [[- abs] 🪄 <]]
          [examples [[[1.0 2.0 + 3 0.001 within?] []]]]]]
[[fibonacci [[definition [1 0 [[+] •🛡️ ▶️ 🔀 👥]]]]]]
🔗 

1.7. Serialization

[read [[spec [[string] [item]]]
       [examples [[["[1 [2] 3]" read] [[1 [2] 3]]]]]]]

[emit [[spec [[item] [string]]]
       [examples [[[[1 [2] 3] emit] ["1 [2] 3"]]]]]]

[parse-edn [[spec [[[list current-output-sequence] [string input] [string input-buffer]]
                   [[list updated-output-sequence] [string remaining-input]]]]
            [examples [[["" "[foo] [ba" 🔳 parse-edn] [" [ba" [[foo]]]]]]]]

[autoformat [[spec [[string] [string]]]
             [examples [[["[[foo bar] [baz [[quux floop] [toop zoop]]]]" autoformat]
                         ["[[foo bar]\n [baz [[quux floop]\n       [toop zoop]]]]"]]]]]]

1.8. Boolean logic

[[[spec [🔳 [word]]]]] ;; self-inserts

[and [[spec [[item item] [item]]]
      [examples [[[1 odd? 2 even? and] []]
                 [[2 3 and] [3]]
                 [[🔳 3 and] [🔳]]
                 [["" 3 and] [🔳]]]]]]

[or [[spec [[item item] [item]]]
     [examples [[[1 odd? 3 even? or] []]
                [[1 2 or] [1]]
                [[🔳 2 or] [2]]
                [[🔳 🔳 or] [🔳]]]]]]

[☯️ [[spec [[item] [boolean]]]
    [examples [[[1 even? ☯️] []]
               [[🔳 ☯️] []]
               [[✅ ☯️] [🔳]]
               [[🔳 ☯️] []]]]]]

1.9. Byte encoding and decoding

[character [[spec [[item] [character]]]
            [examples [[[97 character] [\a]]
                       [[128526 character] [\😎]]]]]]

[encodeitem [[spec [[item] [bytes]]]
             [examples [[["foo" encodeitem] [#b64 "Zm9v"]]
                        [["" encodeitem] [#b64 ""]]
                        [[12 encodeitem] [#b64 "AAAAAAAAAAw"]]
                        [[12.3 encodeitem] [#b64 "QCiZmZmZmZo"]]]]]]

[decodejson [[spec [[string] [item]]]
             [examples [[["12" decodejson] [12]]
                        [["12.01" decodejson] [12.01]]
                        [["\"foo\"" decodejson] ["foo"]]
                        [["{\"foo\": 12, \"bar\": \"baz\"}" decodejson] [[["foo" 12] ["bar" "baz"]] association]]
                        [["[1,\"foo\"]" decodejson] [[1 "foo"]]]]]]]

[encodejson [[spec [[item] [string]]]
             [examples [[[12 encodejson] ["12"]]
                        [[12.01 encodejson] ["12.01"]]
                        [["foo" encodejson] ["\"foo\""]]
                        [[[["foo" 12] ["bar" "baz"]] association encodejson decodejson] [[["foo" 12] ["bar" "baz"]] association]]
                        [[[1 "foo"] encodejson] ["[1,\"foo\"]"]]]]]]

[bytes? [[spec [[item] [boolean]]]
         [examples [[["foo" bytes?] [🔳]]
                    [[#b64 "Zm9v" bytes?] []]
                    [[[#b64 "Zm9v"] bytes?] [🔳]]
                    [["foo" encode bytes?] []]]]]]

[xor [[spec [[item] [item]]]
      [examples [[[10 12 xor] [6]] ;; 10 = 01010, 12 = 01100, 00110, 6
                  [["foo" encode "bar" encode xor] [#b64 "BA4d"]]]]]]

[bits [[spec [[item] [sized]]]
       [definition [encode [[2 radix 8 0 pad] each [🔗] fold] assemble]]
       [examples [[["foo" bits] [[0 1 1 0 0 1 1 0 0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 1]]]]]]]
[[encode [[spec [[item] [bytes]]]
          [definition [[[[] [🗑️ encodeitem]]]
                       decide]]
          [examples [[[12 encode] [#b64 "AAAAAAAAAAw"]]
                     [["foo" encode] [#b64 "Zm9v"]]
                     [["foo" encode encode] [#b64 "Zm9v"]]
                     [["" encode] [#b64 ""]]]]]]

 [radix [[spec [[integer integer] [list]]]
         [definition [[🗑️ 1️⃣ [/] 🛡️ ▶️ 🔀 
                       [*] •🛡️ ▶️
                       •🔀 -
                       🔀 [prepend] 🪄] 🎒
                      [🔳 🔀 [positive?] 🛡️] 🪄
                      ⏳ ▶️ 🗑️]]
         [examples [[[7 2 radix] [[1 1 1]]]
                    [[9 3 radix] [[1 0 0]]]
                    [[255 16 radix] [[15 15]]]]]]]]
🔗

1.10. Strings

[string [[spec [[item] [string]]]
         [examples [[[1 string] ["1"]]
                    [[[97 98 99] string] ["abc"]]
                    [[🔳 string] [""]]]]]]

[format [[spec [[list string] [string]]]
         [examples [[["foo {} bar {} baz" ["abc" "def"] format] ["foo abc bar def baz"]]]]]]

[parse-utf8 [[spec [[[sized current-output] [bytes input] [bytes input-buffer]]
                    [[string updated-output-sequence] [bytes remaining-input]]]]
             [examples [[["hi" encode [226] encode "" parse-utf8] [#b64 "4g" "hi"]]
                        [["hell" encode \o encode "" parse-utf8] [#b64 "" "hello"]]]]]]

[string? [[spec [[item] [boolean]]]
          [examples [[["hi" string?] []]
                     [["" string?] []]
                     [[["hi"] string?] [🔳]]
                     [[✅ string?] [🔳]]]]]]

;; Don't really belong here but good enough for now
[word? [[spec [[item] [boolean]]]
        [examples [[[[foo] 🍫 word?] []]
                   [[✅ word?] []]
                   [[1 word?] [🔳]]
                   [["✅" word?] [🔳]]]]]]

[word [[spec [[item] [word]]]
       [examples [[["foo" word] [[foo] 🍫]]]]]]

[inspect [[spec [[item] [string]]]]]

1.11. Error handling

[error? [[spec [[item] [boolean]]]]]

;; handle is a special word only used to unwind the program on
;; error, if there's no error and we end up reaching this word, we
;; ignore it.
[handle [[spec [🔳 🔳]]
         [definition 🔳]]]

[fail [[spec [[sized] [*]]]]]
[[assert [[spec [[program]
                 [*]]]
          [definition [📸 ;; save stack to print in err message
                       [🛡️] 🐋 ;; run the assertion under the saved stack
                       [🗑️] ;; if passes, drop the saved stack, dont need
                       [string ["assertion failed "] 🪄 🔗 fail]]]]] ;; else throw err

 [🩹 [[spec [[[program error-handler] [program to-attempt]] [program]]]
      [doc "The bandage denotes a recovery, it takes an error-handler
            program, and a program to attempt that may cause an
            error. If the to-attempt program succeeds, the
            error-handler is dropped. Iff the to-attempt program fails
            with an error, the error-handler is invoked on a snapshot
            of the stack when the to-attempt program began."]
      [definition [[📸 [✂️2️⃣ handle] 💉 ▶️
                    [first error?] 🛡️
                    [🗑️ first ✂️1️⃣]
                    [🧦 🗑️]
                    ⚖️ ▶️] 🎒]]
      [examples [[[[+]
                   [🗑️ 1
                    [+] [🗑️ 2 +]
                    🩹 ▶️]
                   🩹 ▶️]
                  [3] "Simple recovery"]

                 [[[1 2 "oh fudge"]
                   [5 +]
                   [🗑️ 5]
                   🩹 🚜 ▶️]
                  [[6 7 5]] "Recover as part of mapping function"]

                 [[[🔀] [🗑️ 🔀] 🩹 ▶️]
                  [🔀] "Recovery with empty stack"]]]]]

 [retry [[spec [[error] [*]]]
         [definition [[unwound] 🔍 ▶️]]
         [examples [[[2 3 "four" * + handle [🗑️ 4] 🪄 retry] [14]]]]]]]
🔗

1.12. Methods

We want a way of adding methods to a word that's already set up as a simple 'decide' form. This will add the method at the beginning - adding it at the end is not good because often there's a catchall condition at the end, and adding beyond that means the new condition is unreachable. Adding at the beginning is not always what the user wants either, though. So maybe this could be improved by taking another argument: a program to combine the item and the existing list (that defaults to prepend here).

[[addmethod [[spec [[[program method] [program condition] [program definition]]
                    [[program newdefinition]]]]
             [definition [[[2️⃣ 1️⃣] prepend] 🎒
                          [0] 🔀 update]]
             [examples [[[[[[[📏 3 >] ["foo" 📮]]
                            [[☯️] ["bar" 📮]]] decide]
                          [📏 1 =] [rest] addmethod]

                         [[[[[📏 1 =] [rest]]
                            [[📏 3 >] ["foo" 📮]]
                            [[☯️] ["bar" 📮]]]
                           decide]]]]]]]

 [method? [[spec [[program] [boolean]]]
           [definition [[[first [[pair?]
                                 [[list?] every?]] every?]
                         [second [decide] unwrap =]]
                        every?]]]]]
🔗

1.13. Database

[[[list selection] [list constraints]]
 [string]]

[[fork [[▶️] 🚜]]
 [triangle [[🔳 [[📤] 🪄 🔀 [[📮] 🛡️ ⚓ 🔀 pair] bail] collect] •🛡️]]
 [indexed-as-property [🔀 indexed
                       [🍫 ⚓ assign] 🚜 •🗑️]]
 [join-all [[first empty] 🛡️ 🔀 [🔗] 🪜]]
 [selectkeys [set [1️⃣ [first] 🐋 contains?] 🎒 🧲]]
 [invert [[reverse] 🚜 association]]

 ;; datalog variables
 [variable? [[[word?]
              [string last \? =]] [▶️] 💯]]
 [variable= [[[pair [variable?] 💯] [=]] [▶️] 💯]] 

 ;; datalog constraints
 [slots [[entity attribute value]]]
 [slot-combos [slots [slots [pair] 🚜] 🚜 join-all]]
 [constraint [🍫 slots reverse label]] 

 ;; links between datalog constraints
 [links [slot-combos
         [[🎁] 🚜 🍫 •🔀 
          [[[🔍] 💉] both] pairwise 
          variable=]
         🧲    
         [🍫 pair ⚓ pair
          [[index] 🔍] 🚜 🔀 zip]
         🚜]]
 [all-links [🔳 ⚓
             [[[[index] 🔍] 🛡️] both ;; lookup the indices of both constraints
              [•🔀] 🪄 ⚓ ;; move the indices under the constraints
              [links] •🛡️
              🔀 [•🗑️ •🗑️ 🔗] 🪄] 

             🪜 🗑️]]
 [format-link [[🔗] 💉 🍫 [string] 🚜
               "c{0}.{1} = c{2}.{3}" 🔀 format]] 

 ;; formatting pieces of query data into text
 [anded-together [" AND " interpose join-all]]

 ;; where clause data processing
 [where-data [[[index] 🔍] 🛡️ 🔀 
              [[[second variable? ☯️]
                [first [index] 🍫 = ☯️]] [▶️] 💯] 🧲 
              [🔀 prepend] 🚜 •🗑️]]
 [format-where [[string] 🚜 
                "c{0}.{1} = :c{0}{1}" 🔀 format]]
 [make-where [first [where] 🔍 anded-together]]
 [format-join [[[[on] 🔍]
                [[where] 🔍]
                [[index] 🔍 string]] [▶️] 🚜
               [🔗 anded-together] 💉 
               "JOIN EAV c{1} ON {0}" 🔀 format]]
 [make-query [rest [[on]
                    [[format-link] 🚜] update
                    [format-join] 🛡️ [🔗] 🔀 assign] 🚜]]

 ;; SQL parameters for rusqlite
 [param-name [[string] 🚜 ":c{0}{1}" 🔀 format]]
 [extract-params [🔳 association 🔀 [[params] 🔍 🔗] 🪜]]


 ;; SELECT clause
 [wordval? [second word?]]
 [invert [[reverse] 🚜 association]]
 [validate [[[second ☯️]
             [first "All selected query variables must appear somewhere in constraints"
              [reason variable] label fail]
             when] 🚜]]
 [select-data [🔀
               [[slots selectkeys invert] 🛡️
                [wordval?] 🧲 🔗 association] 🚜
               🔀
               [[[[index 1️⃣] selectkeys] 🎒 ;; make the program to cut down 
                 🚜 
                 [📏 2 =] 🧲 first [second] 🚜
                 [first number?] [reverse] when] ;; items are in random order due to coming from association, fix the order
                🚜]
               🛡️ ••🗑️ zip
               validate]]

 ;; query 
 [extract-data [[[[🍫 all-links]
                  [first where-data   ; [🔗] 💉 🍫
                   ;; build the query param 🚜
                   [[🔳 🔀
                     [[param-name] 🛡️ [last] 🪄 🎁 🔀 assign]
                     🪜]
                    ;; build the actual query where clauses
                    [[format-where] 🚜]]
                   fork]]
                 fork] 🛡️
                ;; combine extracted items

                [first] 🪄 ;; keep the original constraint to add properties to
                🍫 🍫 [where params on] label 🔗]]
 [format-select [[🍫 🔀
                  string butlast ;; remove the ? from the variable name for result column
                  📮
                  [string] 🚜 %
                  "c{1}.{0} as {2}" 🔀 format] 🚜 ", " interpose join-all]]]

;; This is the program we need to modify that is `query`

[🔀
 ;; expand all combinations of constraints
 [constraint] 🚜
 ;;🔳 prepend ;; an empty constraint to represent the orignal EAV table we're joining with
 [index] indexed-as-property
 triangle
 ;; for each pair of constraints, build the "ON" clause data for the JOIN
 [extract-data] 🚜
 [[extract-params]
  [make-query]
  [make-where]
  [🔀 select-data]] fork 
 •🗑️ ;; don't need original anymore
 🍫 🛟
 [[🔗] 🔍] 🚜  
 🔀 format-select 
 [" " interpose join-all] 🪄 triplet reverse
 "SELECT {0} from EAV as c0 {1} WHERE {2}" 🔀 format
 🔀 ••🗑️]

let
[definition spec] label
[query] 🔀 assign

1.14. Pipes

[pipe? [[spec [[item] [boolean]]]
        [examples [[[timestamps pipe?] []]
                   [[standard pipe?] []]
                   [[[1 2 3] pipe?] [🔳]]
                   [[5 pipe?] [🔳]]]]]]

[animate [[spec [[environment] 🔳]]]]

[attend [[spec [[list] [list]]]]]

[file-in [[spec [[string] [pipe]]]]]

[file-out [[spec [[string] [pipe]]]]]

[handoff [[spec [🔳 [pipe]]]]]

[receiver [[spec [[pipe] [pipe]]]]]

[select [[spec [[[list pipes]] [item pipe [list pipes]]]]]]

[sender [[spec [[pipe] [pipe]]]]]

[serversocket [[spec [[integer string] [pipe]]]]]

[socket [[spec [[integer string] [pipe]]]]]

[standard [[spec [🔳 [pipe]]]]]

[timer [[spec [[integer] [pipe]]]]]

[timestamps [[spec [🔳 [pipe]]]]]

[database [[spec [[[sized params] string] 🔳]]]]

[persist [[spec [[sized] 🔳]]]]
[[pipe-in [[spec [[item] [pipe]]]
           [definition [association
                        [[[type [file] 🍫 =]
                          [🗑️ value file-in]]
                         [[type [stdout] 🍫 =]
                          [🗑️ stdout]]]
                        decide]]]]

 [tunnel [[spec [[item] [pipe]]]
          [definition [association
                       [[[type [ip-host] 🍫 =]
                         [🗑️ 👥
                          [port] 🔍
                          [[address] 🔍] 🪄
                          serversocket]]
                        [[type [ip-client] 🍫 =]
                         [🗑️ 👥
                          [port] 🔍
                          [[address] 🔍] 🪄
                          socket]]]
                       decide]]]]

 [pipe-out [[spec [[item] [pipe]]]
            [definition [association
                         [[[type [file] 🍫 =] 
                           [🗑️ value file-out]]
                          [[type [ip-host] 🍫 =]
                           [🗑️ 👥
                            [port] 🔍
                            [[address] 🔍] 🪄
                            serversocket]]]
                         decide]]]]

 [spit [[spec [[item [item target]] 🔳]]
        [definition [[pipe-in] 🪄 encode 📮 🗑️]]]]

 [slurp [[spec [[pipe] [item]]]
         [definition [[📤] [🔗] fold string [🗑️ 🗑️] 🪄]]]]

 [print [[spec [[string] 🔳]]
         [definition [[standard] 🪄 "\n" 🔗 encodeitem 📮 🗑️]]]]

 ;;[slurp [[spec [[[item target]] [item pipe]]]]]

 [sleep [[spec [[integer] 🔳]]
         [definition [timer 📤 🗑️ 🗑️]]]]

 [future [[spec [[program] [pipe]]]
          [definition [handoff 🔀
                       [[✂️1️⃣ 📸] ;; return entire stack
                        🐋 📮 🗑️] 🎒
                       dictionary 🔀 spawn animate]]
          [examples [[[1 [2 +] future 📤 •🗑️] [1 [3]]]]]]]

 [close [[spec [[pipe] 🔳]]
         [definition [🗑️]]]]]
🔗

1.15. Crypto

[random [[spec [[integer] [bytes]]]]]

[key [[spec [[bytes] [bytes]]]
      [examples [[[["foo" encode key] 2 times =] []]]]]]

[sign [[spec [[[bytes message] [association key]] [bytes]]]]]

[verify [[spec [[[bytes signature]
                 [bytes message]
                 [sized key]]

                [boolean]]]
         [examples [[["foo" encode key "we attack at dawn" encode [sign] 🛡️ verify] []]]]]]
[[delegated [[spec [[[association pubkey]] [program]]]
             [definition [[[;; css cs pk
                            [[hash] [🛡️ 🪄] decorated ;; css csh cs pk
                             🛟 ;; cs css csh pk
                             [verify] 🪄
                             [🔳]  ;; the program to run if the child script isn't authorized
                             ↔️] ;; runs the child script if the sig on its hash is verified
                            [🗑️ 🗑️ ;; the sig and (empty) child script -> pk sig msg;; sig msg pk
                             verify]
                            [👥] •🪄 ↔️]
                           [🔳] 🩹]
                          🔀 prepend]]]] ;; prepend the pubkey

 [hash [[spec [[item] [bytes]]]
        [definition [[[[bytes?] [hashbytes]]
                      [[] [encode hash]]]
                     decide]]]]]
🔗

1.16. Time and date

[[milliseconds [[spec [[integer] [integer]]]
                [definition 🔳]]]

 [seconds [[spec [[integer] [integer]]]
           [definition [1000 *]]]]

 [minutes [[spec [[integer] [integer]]]
           [definition [seconds 60 *]]]]

 [hours [[spec [[integer] [integer]]]
         [definition [minutes 60 *]]]]

 [days [[spec [[integer] [integer]]]
        [definition [hours 24 *]]]]]
🔗

1.17. Nested Environments

[environment [[spec [[sized] [environment]]]
              [examples [[[[[program [1 2 3]]] environment eval-step [stack] 🔍] [[1]]]]]]]

[environment? [[spec [[item] [boolean]]]
               [examples [[[[[program [1 inc]]] environment environment?] []]
                          [[[[program [1 inc]]] environment?] [🔳]]]]]]

[eval-step [[spec [[environment] [environment]]]
            [examples [[[[[program [1 inc]]] environment
                         eval-step eval-step
                         [stack] 🔍]
                        [[2]]]]]]]

[evaluate [[spec [[item] [environment]]]
           [examples [[[[[program [1 2 3 4 + *]]] environment
                        evaluate
                        [stack] 🔍]
                       [[14 1]]]]]]]

[finished? [[spec [[environment] [boolean]]]
            [examples [[[[[program [1 2 3 4 + *]]] environment
                        finished?]
                       [🔳]]
                      [[[[program [1 2 3 4 + *]]] environment
                        evaluate
                        finished?]
                       []]]]]]

[using [[spec [[[list modules] [sized env]] [environment]]]]]

[use [[spec [[[program [list modules]] [*]]]]
      [definition [stage 🔀 ;; lm env
                   [[stack] [📸] •🐋 assign] 🪄 ;; capture the stack at runtime
                   using ;; set up the resolver 
                   evaluate ;; execute the program in the inner environment
                   [stack] 🔍 restore]]]] ;; replace the stack with the result from the inner env
[tos [[spec [[environment] [item]]]
      [definition [[stack] 🔍 first]]
      [examples [[[[[stack [1 2 3]]
                    [program [[+] 🪜]]]
                   tos]
                  [1]]]]]]

[top [[spec [[environment] [item]]]
      [definition [[program] 🔍 first]]
      [examples [[[[[stack [1 2 3]]
                    [program [[+] 🪜]]]
                   toe]
                  [[+]]]]]]]

[stage [[spec [[program] [environment]]]
        [definition [[program] label environment]]]]

[capture [[spec [[environment] [environment]]]
          [doc "Capture the outer stack and assign it to the inner env's stack"]
          [definition [[stack]
                       [📸] •🐋
                       assign]]]]

[spawn [[spec [[program dictionary] [environment]]]
        [definition [[📸] •🪄 ;; p d s
                     [program dictionary stack] label
                     environment]]
        [examples [[[1 2 3 dictionary [🔀 👥] spawn]
                    [1 2 3 [[program [🔀 👥]] [stack [3 2 1]]] environment]]]]]]

[confine [[spec [[[program module] dictionary] [*]]]
          [definition [spawn evaluate [stack] 🔍 restore]]]]

1.17.1. Debugging

[[break [[spec [[[program condition] environment]
                [[program condition] environment]]]
         [definition [[[[🔀 something?] ;; still running
                        [▶️ ☯️]] ;; check condition not true yet
                       [▶️]
                       every?] ;; break?
                      [[eval-step] 🪄]  ;; evaluate the environment one step]]]]

 [breakpoint [[spec [🔳 🔳]]
              [definition 🔳]]]

 [sprint [[spec [[environment]
                 [environment]]]
          [definition [[[program 0] 🔍 🎁 [breakpoint] =] break
                       🗑️ ;; the condition
                       🔳 [eval-step] when]]]] ;; advance past the breakpoint word if the program isn't complete


 [advance [[spec [[environment] [environment]]]
           [definition [👥 [program] 🔍 📏 🔀 ;; count up the program length, we'll run until it's smaller than this
                        [[program] 🔍 📏 ;; only stop if env's program empty or shorter than we started off
                         [[positive?] [<=]] [🛡️ ▶️] 💯 ▶️] 🛡️ 
                        [🗑️ eval-step] ;; evaluate the environment one step
                        ⏳ ▶️
                        •🗑️]]]] ;; drop the program length item

 [stepper [[spec [🔳 [program]]]
           [definition [[eval-step 👥]]]]]

 [tracer [[spec [[program] [[program generator]]]]
          [definition [stage stepper]]]]

 [dump [[spec [🔳 🔳]]
        [definition [📸 🎁 emit autoformat print]]]]

 [heatmap [[spec [[program] [association]]]
           [definition [[tracer
                         ;; what item is being ▶️d
                         [[program] 🔍 [first]
                          ;; don't emit 🔳 or the execution stops, use 0 instead
                          bail 0 or]
                         each 
                         [word?] keep ;; count only words, which filters out the 0's from above
                         frequencies] •🛡️]]]]]


🔗
[[evaluating? [[program] 🔍 [evaluate] starts?]]
 [with-innermost [[🔳 🔀
                   [[evaluating?]
                    [[stack 0] 👥 [🔍] 🪄 🔀 [🔗] 🪄 ] ;; append the next part of the path to the accumulator
                    ⏳ 🔀] 🛡️ ••🗑️]
                  🪄 ;; under the stepping prog
                  [update] •🛡️ flip 🗑️

                  ;; find which envs are finished and remove
                  ;; 'evaluate' from parent
                  [0 -2 slice 👥] [collect] ••🛡️ 
                  [[[[[evaluating?]
                      [[stack 0] 🔍 finished?]]
                     [▶️] 💯]
                    [[program] [rest] update]
                    when]
                   [update] •🛡️ flip 🗑️ 🗑️]
                  🪜]]]
🔗

2. Issues

2.1. DONE Get rid of platform-specific definitions

2.2. DONE fix evaluate

[[program [1 1 +]]] environment evaluate [stack] 🔍

[[2]]

2.3. TODO merkle tree functions

"foo" "bar" join hash "foobar" hash =
yes

First let's figure out how to represent a tree:

;[5 [[3 [[1c 🔳]
;        [2c 🔳]]]
;    [4 [[3c 🔳]]]]]
[[hash 🔳]
 [children [second]]
 [data [first]]
 [node [🔳 pair]]
 [empty-node [#b64 "" hash node]]
 [child [[children] 🪄 get]]
 [addchild [[pop] 🪄 📮 📮]]
 [rawpath [1 [interpose] 🛡️ 🔀 prepend •🗑️]]
 [siblings [🔳 node ⚓ [addchild] 🪄 addchild]]
 ;[path [🔳 [📤 🔀 [child] 🪄 path] [drop] ⚖️]]
 [path [dec 2 radix rawpath]]
 [parent [butlast butlast]]
 [rehash [[children [data] 🚜] 🛡️
          [first] 🛡️ empty 🔀 [join] 🪜
          hash wrap [0] 🔀 update]]
 ;; lopsidedtree n
 [balance 🔳]
 ;; node tree cur-ct
 [add [[👥 path [pop zero?] [parent] when] •🪄  ;; node tree path ct
       •🔀 ;; node path tree ct
       🔳]]
 [add [[odd?]
       ;; insert an unbalanced node (empty sibling)
       [empty-node siblings [path parent]]
       ;; otherwise replace the empty sibling
       🔳
      ]]]
; ["" drop
;  ;[0 🔳] 1 node addchild 2 node 3 node addchild addchild
;  ;[1 0]  1 [interpose] shield 🔀 📮 •🗑️ 🔍
;  "foo"  hash node "bar"  hash node siblings
;  ;; update the root node
;  rehash
;  ; now add a new sibling
;  "baz"  hash node siblings
;  rehash
;  3 path [pop zero?] [butlast butlast] 🔳 ⚖️
;  ;dump
;  ["quux" hash node siblings rehash ] update
; ]
[["foo" "bar" "baz" "quux"] [node] 🚜 🔳
let
[["foo" 🔳]
 ["bar" 🔳]
 ["baz" 🔳]
 ["quux" 🔳]]
  • 1234

    • 12
      • 1
      • 2
    • 34
      • 3
      • 4
    • 5
    • 6
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["bazquux" [["baz" 🔳]
                          ["quux" 🔳]]]]]
["" 🔳]

interpose impl

[1 3 4] [foo] unwrap interpose
[1 foo 3 foo 4]
[0 [[1 🔳]
    [2 [[3 🔳]]]]]
  [1 0] 1 [interpose] 🛡️ 🔀 prepend 0 📮 •🗑️ [inc] update
[0 [[1 🔳]
    [2 [[4 🔳]]]]]

We need a function that, given a number n, gives the path in the merkle tree. eg, 8 would be 1 1 1. Is it just n-1 in binary? 6 would be 1 0 1. Ok so just write a function to expand binary digits:

8 dec 2 radix
[1 1 1]
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["baz" 🔳]]] [1 1] [🗑️ 🗑️ "hi" "there"] update
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              "there"]]
[[hash 🔳]
 [children [second]]
 [data [first]]
 [node [🔳 pair]]
 [child [[children] 🪄 get]]
 [addchild [[pop] 🪄 📮 📮]]
 [siblings [🔳 node ⚓ [addchild] 🪄 addchild]]
 ;[path [🔳 [📤 🔀 [child] 🪄 path] [🗑️] ⚖️]]
 [path [dec 2 radix nodepath]]
 [rehash [[children [data] 🚜] 🛡️ [first] 🛡️ empty 🔀 [join] 🪜 hash wrap [0] 🔀 update]]]
[["foobarbaz" [["foobar" [["foo" 🔳]
                          ["bar" 🔳]]]
               ["baz" 🔳]]]
 [1 1]

 ["bazquux" [["baz" 🔳]
             ["quux" 🔳]]]
 assign]
let
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["bazquux" [["baz" 🔳]
                          ["quux" 🔳]]]]]
[["bazquux" [["baz" 🔳]
             ["quux" 🔳]]]
 [1 1]
 ["foobarbaz" [["foobar" [["foo" 🔳]
                          ["bar" 🔳]]]
               ["baz" 🔳]]]]
reverse unwrap assign
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["bazquux" [["baz" 🔳]
                          ["quux" 🔳]]]]]
[
 [children [second]]
 [data [first]]
 [node [🔳 pair]]
 [addchild [[pop] 🪄 📮 📮]]
 [siblings [🔳 node ⚓ [addchild] 🪄 addchild]]
 [nodepath [1 [interpose] 🛡️ 🔀 prepend •🗑️]]
 [padded [[[[📏] 🛡️] 🐋 -] 🪄
          🔀 repetition
          🔀 join]]
 [path [[dec 2 radix] 🪄 2 log ceiling 0 padded nodepath]] ;; item-ct index
 [depth 🔳]

 [rehash [[children [data] 🚜] 🛡️
          [first] 🛡️ empty 🔀
          [join] 🪜
          hash
          wrap [0] 🔀 update]]
 [joiner [[2 2 partition
           [[📏 1 =] [🔳 📮] when
            unwrap siblings] each]
          assemble [rehash] 🚜]]
 [merkle [[hash node] 🚜
          [📏 1 >] [joiner]]]]
[["a" "b" "c" "d" "e"]
 📏
 5 ;; 2nd item
 🔀 path ]
let
[1 1 1 0 1 0]
[[#b64 "FO3l6Ol62TcjJ3KPUJm5VgSjlZPKw704o0OtdiBSE+c=" [[#b64 "5aAf7hTg7VxIcU8iGA8lrYNltT+XefedxKPX6Tlj+Uo="
                                                        [[#b64 "ypeBEsobvcr6wjGzmiPcTaeG7/gUfE5yuYB3ha/uSLs=" 🔳]
                                                         [#b64 "PiPoFgA5WUoziU9lZOGxNIu9egCI1CxKy3PurtWcAJ0=" 🔳]]]
                                                       [#b64 "v/4LNNuha8b6wXwIusVdZ2ze1aSt5B/iyZJKXd6PPls=" [[#b64 "Ln0sA6lQeuJl7PW1NWiFpTOTogKdJBOUmXJloaJa78Y="
                                                                                                              🔳]
                                                                                                             [#b64 "GKw+c0PwFokMUQ6T+TUmEWnZ4/VlQ2Qpgw+vCTT0+OQ=" 🔳]]]]]]
[1 1 1] 5 0 [[[📏] 🛡️] 🐋 -] 🪄
        🔀 repetition
        🔀 join
[0 0 1 1 1]

2.4. CANCELED Make taker/dropper more flexible

Goal: implement drop and drop-while with the same logic

Canceled - the commonality between drop and drop-while are too small to be worth trying to factor out.

[1 2 3 4 5] [📤]
3
[[[positive?]
  [[generate 🗑️] 🪄 dec]
  while
  [generate 🔀] 🪄 🛟]
 bail]
collect
[4 5]
[[[positive?] [[generate 🗑️]
               🪄 dec]
  while [generate 🔀]
  🪄 🛟]
 bail]
0 [📤] 🔳

This is what drop-while looks like

🔳 [📤]
[positive?]
🔳 ;; the state (whether threshold reached)
[🔳 ;; condition - whether we've finished dropping or not 
 [[generate] •🐋] ;; true - pass everything else through
 [[[generate] •🐋] ;; prime init
  [[[👥] •🐋 execute] bail] ;; bring pred up and exec it
  [🗑️] ;; if pred passes drop the value
  prime ;; after this should have value on top
  [🗑️ true] 🪄 ;; set flag
 ] ;; false - generate, check pred, repeat
 ⚖️]
collect
🔳 [🔳 [[generate] •🐋]
    [[[generate] •🐋]
     [[[👥] •🐋 execute] bail]
     [🗑️] prime [🗑️ yes]
     🪄]
    ⚖️]
yes [positive?] [📤] 🔳

Author: Skyrod Vactai

Created: 2025-03-12 Wed 23:58

Validate