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 =] [yes] "Same numbers are equal"]
               [[1 1.0 =] [yes] "Same value integer and float are equal"]
               [[[1] [] =]  [[]] "Number and Nothing are unequal"]
               [[[1 [[]]] [1 [[]]] =] [yes] "Same nested list with numbers are equal"]
               [[[1.0 ["foo"]] [1.0 ["foo"]] =] [yes] "Same nested list with string are equal"]
               [["hi" "hi" =] [yes] "Same strings are equal"]
               [["hi" "there" =] [[]] "Different strings are unequal"]
               [[\h \h =] [yes] "Same characters are equal"]
               [[\h \i =] [[]] "Different characters are unequal"]
               [["hi" encode "hi" encode =] [yes] "Same bytes are equal"]
               [["hi" encode "there" encode =] [[]] "Different bytes are unequal"]
               [[[] yes =] [[]] "Different booleans unequal"]
               [[[1.0 ["foo"]] [1.0 ["bar"]] =]  [[]] "Nested lists with different strings are unequal"]
               [[[] [] =] [yes] "'Nothing' is equal to itself"]
               [[[] [] association =] [yes] "List/Association empty container types are equal"]
               [[[] [] set =] [yes] "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 =] [yes] "Sets constructed from different lists are equal"]]]]]

[compare [[spec [[item item] [word]]]
          [examples [[["a" "b" compare] [[less] unwrap] "string lexicographical order with single character inequality"]
                     [["a" "a" compare] [[equal] unwrap] "string lexicographical order with single character equality"]
                     [[1 1 compare] [[equal] unwrap] "Same integer compares equal"]
                     [[2 1 compare] [[greater] unwrap] "Integer order inequality"]
                     [[1 [foo] unwrap compare] [[less] unwrap] "Integer/list order inequality"]
                     [[1 "foo" encode compare] [[less] unwrap] "Integer/byte order inequality"]
                     [[[foo] unwrap "foo" encode compare] [[less] unwrap] "Word/string order inequality"]
                     [["foo" encode "foo" compare] [[less] unwrap] "String order equaltiy"]
                     [[[] [[]] unwrap compare] [[equal] unwrap] "Unwrapped Nothing value equality"]
                     [[[] [1] rest compare] [[equal] unwrap] "Nothing/emptied container equality"]]]]]

;; TODO these should be in terms of compare and not limited to numbers
[< [[spec [[number number] [boolean]]]
    [examples [[[1 2 <] [yes] "Integer is less"]
               [[2.2 1.1 <] [[]] "Float is not less"]
               [[1 2.2 <] [yes] "Integer/float is less"]
               [[1.1 1.1 <] [[]] "Equal floats is not less"]]]]]

[> [[spec [[number number] [boolean]]]
    [examples [[[2 1 >] [yes] "Integer is greater"]
               [[1.1 2.2 >] [[]] "Float is not greater"]
               [[2.2 1 >] [yes] "Integer/float is greater"]
               [[1.1 1.1 >] [[]] "Equal floats is not greater"]]]]]

[<= [[spec [[number number] [boolean]]]
     [examples [[[1 2 <=] [yes] "Integer is less/equal"]
                [[2.2 1.1 <=] [[]] "Float is not less/equal"]
                [[1 2.2 <=] [yes] "Integer/float is less/equal"]
                [[1.1 1.1 <=] [yes] "Equal floats is less/equal"]]]]]

[>= [[spec [[number number] [boolean]]]
     [examples [[[2 1 >=] [yes] "Integer is greater/equal"]
                [[1.1 2.2 >=] [[]] "Float is not greater/equal"]
                [[2.2 1 >=] [yes] "Integer/float is greater/equal"]
                [[1.1 1.1 >=] [yes] "Equal floats is greater/equal"]]]]]
[min [[spec [[number number] [number]]]
      [definition [[<] [] [swap] if drop]]
      [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 [[>] [] [swap] if drop]]
      [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

[drop [[spec [[item] []]]
       [examples [[[1 2 3 drop] [1 2] "Drop integer on ToS"]
                  [[1 2 3 [a b c] drop] [1 2 3] "Drop list on ToS"]]]]]

[clone [[spec [[[item a]]
               [[item a] [item a]]]]
        [examples [[[1 2 3 clone] [1 2 3 3] "Clone integer on ToS"]]]]]

[evert [[spec [[list] [list *]]]
        [examples [[[1 2 3 [4 5 6] evert] [6 5 4 [3 2 1]] "Evert a list of integers with the stack"]]]]]
[clonedown [[spec [[[item a] [item b]]
                   [[item a] [item b] [item b]]]]
            [definition [swap clone float]]
            [examples [[[1 2 3 clonedown] [1 2 2 3] "Clone the 2nd item on the stack"]]]]]

[clonedeep [[spec [[[item a] [item b] [item c]]
                   [[item a] [item b] [item c] [item c]]]]
            [definition [[clonedown] dip]]
            [examples [[[1 2 3 4 clonedeep] [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 [clonedown swap]]
       [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 [clone sink]]
        [examples [[[1 2 3 under] [1 3 2 3] "Copy the ToS to the 2nd item"]]]]]

[dropdown [[spec [[[item a] [item b]] [[item b]]]]
           [definition [swap drop]]
           [examples [[[1 2 3 dropdown] [1 3] "Drop the 2nd item"]]]]]

[dropdeep [[spec [[[item a] [item b] [item c]] [[item a] [item b]]]]
           [definition [float drop]]
           [examples [[[1 2 3 dropdeep] [2 3] "Drop the 3rd item"]]]]]

[snapshot [[spec [[] [list]]]
           [doc "Save the whole stack as a list on the stack"]
           [definition [[] evert clone evert unwrap]]
           [examples [[[1 2 3 snapshot] [1 2 3 [3 2 1]] "Copy the stack to ToS"]
                      [[snapshot] [[]] "Copy stack to ToS when stack is empty"]]]]]

[restore [[spec [[list] [*]]]
          [definition [evert drop]]
          [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.

[swap [[spec [[[item a] [item b]]
              [[item b] [item a]]]]
       [examples [[[1 2 3 swap] [1 3 2] "Swap top two items"]]]]]

[swapdown [[spec [[[item a] [item b] [item c]]
                  [[item a] [item c] [item b]]]]
           [examples [[[1 2 3 swapdown] [2 1 3] "Swap 2nd and 3rd items"]]]]]

[float [[spec [[[item a] [item b] [item c]]
               [[item c] [item a] [item b]]]]
        [examples [[[1 2 3 float] [2 3 1] "Move 3rd item to ToS"]]]]]

[sink [[spec [[[item a] [item b] [item c]]
              [[item b] [item c] [item a]]]]
       [examples [[[1 2 3 sink] [3 1 2] "Move ToS to 3rd item"]]]]]
[flip [[spec [[[item a] [item b] [item c]]
               [[item c] [item b] [item a]]]]
        [definition [float swapdown]]
        [examples [[[1 2 3 flip] [3 2 1] "Swap ToS and 3rd item"]]]]]

1.3. Program execution

[execute [[spec [[program] [*]]]
          [examples [[[[1 2 +] execute] [3] "Execute a program"]
                     [[1 2 [] execute] [1 2] "Execute an empty program"]
                     [[1 2 [[+] execute] execute] [3] "Nested execution"]]]]]

[branch [[spec [[[program no-branch]
                 [program yes-branch]
                 [item condition]]
                [*]]]
         [examples [[[5 yes [3 *] [4 +] branch] [15] "Branch on true condition"]
                    [[6 [] [3 *] [4 +] branch] [10] "Branch on false condition"]]]]]

[recur [[spec [[[program rec2]
                [program rec1]
                [program yes-branch]
                [program pred]]
               [*]]]
        [examples [[[3
                     [1 <=] [] [clone dec] [execute *]
                     recur]
                    [6]
                   "Recur with reduction"]]]]]

[loop [[spec [[program [item flag]] [*]]]
       [examples [[[10 yes [-2 * clone 50 <] loop] [160] "Looping"]
                  [[10 [] [-2 * clone 50 <] loop] [10] "Looping with false initial condition is no-op"]]]]]


[dip [[spec [[program [item a]] [[item a] *]]]
      [examples [[[1 8 [inc] dip] [2 8] "Dipping a program under ToS"]
                 [[1 2 [dec] unwrap
                   [+] dip] [3 [dec] unwrap] "A bare word on stack is left intact and not executed"]]]]]

;; TODO: This depends on `if` so might need to move elsewhere, maybe Methods?
[decide [[spec [[[list test-expr-pairs]] [*]]]
         [doc "Takes a list of choices (pairs of test, program) and
                executes the first program whose test passes. if none
                pass, returns 'nothing'. Stack is reset between
                testing conditions."]
         [examples [[[5 [[[3 =] ["three"]]
                         [[5 =] ["five"]]
                         [[7 =] ["seven"]]
                         [[yes] ["something else"]]]
                      decide]
                     [5 "five"] "Decide with matching condition"]

                    [[9 [[[3 =] ["three"]]
                         [[5 =] ["five"]]
                         [[7 =] ["seven"]]
                         [[yes] ["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"]]]]]
[decorate [[spec [[list program] [program]]]
           [definition [[[wrap] dip put] step]]
           [examples [[[[1 inc] [foo bar] decorate] [[[[1 inc] foo] bar]]
                       "Decorate a program with a series of modifiers"]]]]]

[decorated [[spec [[list program] [*]]]
            [definition [decorate execute]]
            [examples [[[1 2 [+] [bail shield] decorated] [1 2 3] "Execute a decorated program"]]]]]

;; TODO: implement as axiom (which would depend on 'restore' which should also be axiom?)
[shield [[spec [[program]
                [item]]]
         [doc "Runs program keeping top of stack produced but protects existing items from being consumed."]
         [definition [[snapshot] dip inject first]]
         [examples [[[1 2 3 [=] shield] [1 2 3 []] "Execute a program shielding the stack from consumption"]]]]]

[shielddown [[spec [[program item]
                    [item]]]
             [definition [shield dropdown]]
             [examples [[[1 2 3 [=] shielddown] [1 2 []] "Execute a program consuming only the original ToS"]]]]]

[shielddeep [[spec [[[program p] [item consumed] [item consumed]]
                    [[item result]]]]
             [definition [shield [drop drop] dip]]
             [examples [[[1 2 3 [+ +] shielddeep] [1 6] "Execute a program consuming only the original top 2 items"]]]]]

[if [[spec [[[program no-branch]
             [program yes-branch]
             [program condition]]
            [*]]]
     [definition [[shield] dipdown branch]]
     [examples [[[5 [5 =] [3 *] [4 +] if] [15] "Conditional with true predicate"]
                [[6 [5 =] [3 *] [4 +] if] [10] "Conditional with false predicate"]]]]]

[when [[spec [[[program yes-branch]
               [program condition]]
              [*]]]
       [definition [[] if]]
       [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"]]]]]

;; TODO: drop dependency on 'decorated'
[dipdown [[spec [[program
                  [item a]
                  [item b]]
                 [[item a] [item b] *]]]
          [definition [[dip dip] decorated]]
          [examples [[[1 2 3 [inc] dipdown] [2 2 3] "Dip program under top two items"]]]]]

[dipdeep [[spec [[program
                  [item a]
                  [item b]
                  [item c]]
                 [[item a] [item b] [item c] *]]]
          [definition [[dipdown dip] decorated]]
          [examples [[[1 2 3 4 [inc] dipdeep] [2 2 3 4] "Dip program under top 3 items"]]]]]

[dive [[spec [[program [item a]] [item [item a] *]]]
       [definition [dip swap]]
       [examples [[[4 5 6 [+] dive] [6 9] "Dip program and move result to ToS"]]]]]

[divedown [[spec [[program [item a] [item b]]
                  [item [item a] [item b] *]]]
           [definition [dipdown float]]
           [examples [[[5 6 7 8 [+] divedown] [7 8 11] "Dip under top 2 items and move result to ToS"]]]]]

[divedeep [[spec [[program [item a] [item b] [item c]]
                  [item [item a] [item b] [item c] *]]]
           [definition [wrap [divedown] join dip swap]]
           [examples [[[4 5 6 7 8 [+] divedeep] [6 7 8 9] "Dip under top 3 items and move result to ToS"]]]]]

[inject [[spec [[program list]
                [list]]]
         [doc "Inject the quoted program into the list below
                     it (runs the program with the list as its
                     stack).  Does not affect the rest of the stack."]
         [definition [swap evert take dip evert]]
         [examples [[[1 2 3 [4 5 6] [* +] inject] [1 2 3 [26]] "Inject program into list as if it's the stack"]]]]]

[while [[spec [[[program body]
                [program pred]]
               [*]]]
        [definition [swap [shield] decorate ;; add shield to the pred program
                     clone dipdown ;; run it on the previous ToS
                     join loop]]
        [examples [[[3 [0 >] [clone dec] while] [3 2 1 0] "While loop"]]]]]

[until [[spec [[[program body]
                [program pred]]
               [*]]]
        [definition [swap ;; pred body
                     [not] join ;; reverse logic
                     [shield] decorate ;; add shield to the pred program -> pred body
                     join ;; [body ..  pred]
                     yes swap ;; run at least once
                     loop]]
        [examples [[[2 [even?] [inc] until] [4] "Until loop"]]]]]

[times [[spec [[[integer howmany]
                [program body]]
               [*]]]
        [definition [swap
                     [dec] swap put [dip] join ;; build [dec body dip]
                     [0 >] swap
                     while
                     drop]]
        [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 swap] 3 times] [3 2] "Can run a program multiple times"]]]]]

[primrec [[spec [[[program rec1]
                  [program exit]
                  [number repetitions]]
                 [*]]]
          [definition [[execute] swap join ;; add execute to rec1 to be recurs rec2
                       [[drop] swap join] dip ;; add drop to exit condition
                       [[zero?]] dipdown  ;; put the condition on bottom
                       [[clone dec]] dip ;; add the r1
                       recur]] ;; now its generic recur
          [examples [[[5 [1] [*] primrec] [120] "Simple countup loop"]]]]]

[bail [[spec [[program] [*]]]
       [definition [[swap] [execute] [drop] if]]
       [examples [[[[] [inc] bail] [[]] "Can bail on invalid input"]
                  [[1 [inc] bail] [2] "Valid input doesn't bail"]]]]]

1.4. Collections

[join [[spec [[sized sized] [sized]]]
        [examples [[[["a" "b"] ["c" "d"] join] [["a" "b" "c" "d"]] "Join two collections of strings"]
                   [["ab" "cd" join] ["abcd"] "Join two strings"]
                   [["ab" encode "cd" encode join "abcd" encode =] [yes] "Two joined byte seqs are equal to the combined literal"]
                   [[[[a b] [c d]] association [[e f] [a g]] join] [[[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  join] [[[a b] [e f] [c d]] association] "Joining assoc+list -> assoc, 2nd arg keys take priority"]
                   [[[a b c d] set [a e] join] [[a b c d e] set] "Join set with list -> set"]
                   [[[a e] [a b c d] set join] [[a b c d e] set] "Join list with set -> set"]
                   [["" "" join] [""] "Join two empty strings -> empty string"]
                   [["" [1 2 3] join] [[1 2 3]] "Join empty string + list -> list (identity)"]
                   [["a" [\b \c] join] ["abc"] "Join a string with a list of chars -> string"]
                   [[[\b \c] "a" join] ["bca"] "Join a list of chars with string -> string"]
                   [["" [\b \c] join] ["bc"] "Join an empty string with list of chars -> string"]
                   [["abc" [\d \e 12] join] [[\a \b \c \d \e 12]] "Join a string with list -> list"]
                   [["abc" [] join] ["abc"] "Join a string with empty list -> string"]
                   [["" [] join] [""] "Join empty string with empty list -> string"]
                   [[[1 2 3] set [4 4 4] join] [[1 2 3 4] set] "Join set with list -> set"]]]]]

 [put [[spec [[item receptacle] [receptacle]]]
       [examples [[[[] 1 put] [[1]] "Put integer into empty list"]
                  [[[1 2 3] 4 put] [[1 2 3 4]] "Put integer into list"]
                  [["foo" \d put] ["food"] "Put character into string"]
                  [["foo" encode 32 put string] ["foo "] "Put byte into byte array"]]]]]

 [count [[spec [[sized]
                [number]]]
         [examples [[[["a" "b" "cd"] count] [3] "Count list of strings"]
                    [["abcd" count] [4] "Count chars in string"]
                    [["abcd" encode count] [4] "Count bytes in byte array"]
                    [[[[a b] [c d]] association count] [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"]]]]]

 [step [[spec [[program dispenser] [*]]]
        [examples [[[1 [2 3 4] [*] step] [24] "Step through numbers doing arithmetic"]
                   [[1 [] [*] step] [1] "Stepping through empty list is no-op"]]]]]

 [take [[spec [[dispenser] [item dispenser]]]
        [examples [[[["a" "b" "c"] take] [["b" "c"] "a"] "Take a string from a list"]
                   [[[1 2 3] take] [[2 3] 1] "Take a number from a list"]
                   [[[[a "foo"] [b "foo"] [c "foo"]] take dropdown second] ["foo"] "Take an entry from association is nondeterministic"]
                   [[[1 3 5 7 9] set take dropdown odd?] [yes] "Take item from set is nondeterministic"]]]]]

 [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"]]]]]

 [wrap [[spec [[item] [list]]]
        [examples [[[1 wrap] [[1]] "Wrap a number"]
                   [[[1 2] wrap] [[[1 2]]] "Wrap a list"]]]]]

 [unwrap [[spec [[list] [*]]]
          [examples [[[[1] unwrap] [1] "Unwrap a list of one item"]
                     [[[] unwrap] [] "Unwrap an empty list is a no-op"]
                     [[[1 2 3] unwrap] [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"]]]]]

 [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 [[[[[count] dive] shield slice]
                     [0 swap slice]]
                    [execute] map
                    [drop drop] dip unwrap]]
       [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?] [yes] "Empty list is empty"]
                     [[1 empty?] [[]] "Number is not empty"]
                     [["" empty?] [yes] "Empty string is empty"]
                     [[[foo] empty?] [[]] "Non-empty list is not empty"]]]]]

 [pad [[spec [[[item padding] [integer newsize] sized] [sized]]]
       [definition [[[[count] shield] dive -] dip
                    swap repeat
                    swap join]]
       [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"]]]]]

 [list? [[spec [[item] [boolean]]]
         [examples [[[[1] list?] [yes] "A list is a list"]
                    [[[] list?] [yes] "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"]]]]]

 [pack [[spec [[[list template]] [list]]]
            [examples [[["x" [foo] [bar] unwrap
                         [*2 [*1 x **2] c d 1 2 3] pack]
                        ["x" [[foo] [bar x foo] c d 1 2 3]]
                       "Packing values from the stack, into a template"]]]]]
[something? [[spec [[item] [boolean]]] 
             [definition [empty? not]]
             [examples [[[1 something?] [yes] "A number is something"]
                        [[[] something?] [[]] "Empty list is not something"]
                        [["" something?] [[]] "Empty string is not something"]]]]]

[first [[spec [[ordered] [item]]]
        [definition [take dropdown]]
        [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 [take drop]]
       [examples [[[[1 2 3] rest] [[2 3]] "Take rest of list"]
                  [["foo" rest] ["oo"] "Take rest of string"]]]]]

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

[prepend [[spec [[item sized]
                 [sized]]]
          [definition [wrap swap join]]
          [examples [[[[1 2] 3 prepend] [[3 1 2]] "Prepend to list"]
                     [["oo" \f prepend] ["foo"] "Prepend to string"]]]]]

[every? [[spec [[program sized] [boolean]]]
         [definition [[swap]
                      [[take] dip clone [float [shielddown] dive] dive
                       []
                       [drop every?]
                       [dropdown dropdown] if]
                      [drop drop yes] if]]
         [examples [[[[2 4 6] [even?] every?] [yes] "Every number matches predicate"]
                    [[[2 4 5] [even?] every?] [[]] "Not every number matches predicate"]
                    [[[] [[]] every?] [yes] "Every item in empty list matches any predicate"]
                    [[[2 4 6] [] every?] [yes] "Every item in list matches empty predicate"]
                    [[11 [2 4 6] [+ odd?] every?] [11 yes] "Stack is shielded from predicate"]
                    [[12 [[even?] [positive?] [3 mod 0 =]] [execute] every?] [12 yes] "Can check list of predicates with execute predicate"]]]]]

[any? [[spec [[program sized] boolean]]
       [definition [[swap]
                    [[take] dip clone [float [shielddown] dive] dive
                     []
                     [dropdown dropdown]
                     [drop any?] if]
                    [drop drop []] if]]
       [examples [[[[2 4 6] [even?] any?] [yes] "Any number matches predicate"]
                  [[[3 5 7] [even?] any?] [[]] "No number matches predicate"]
                  [[[] [yes] any?] [[]] "No item in empty list matches any predicate"]
                  [[[[] 2 4 6] [] any?] [2] "Empty predicate returns first truthy item"]
                  [[11 [3 5 6] [+ odd?] any?] [11 yes] "Stack is shielded from predicate"]
                  [[-15 [[even?] [positive?] [3 mod 0 =]] [execute] any?] [-15 yes] "Can check list of predicates with execute predicate"]]]]]

[map [[spec [[program sized] [list]]]
      [definition [[] sink ;; put empty results below list
                   [swap [*1 shielddown] dip swap put] pack
                   step]]

      [examples [[[[1 2 3] [inc] map] [[2 3 4]] "Pass each item through a program"]

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

                 [[7 9 [+] [] map] [7 9 [+]] "Empty program is a no-op"]]]]]

[filter [[spec [[program sized] [list]]]
         [definition [[] sink ;; put empty results below list
                      [swap [*1 shield] dip swap
                       [] [drop swap put] [drop dropdown]
                       if]
                      pack
                      step]]
         [examples [[[[1 2 3] [odd?] filter] [[1 3]] "Filter a list with predicate"]
                    [[[2 4 6] [odd?] filter] [[]] "Filter with predicate that matches no items"]
                    [[33 [1 2 3] [33 + odd?] filter] [33 [2]] "Filter predicate uses existing stack items"]]]]]

[sort [[spec [[program sized] [list]]]
       [definition [[clone **1 pair] pack
                    map 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"] [count] sort] [["Bob" "Alice" "Charlie"]] "Sort list of strings by length"]]]]]

[repeat [[spec [[[integer howmany]
                 item]
                [list]]]
         [definition [[] sink [wrap [put] join] dip times]]
         [examples [[["hi" 3 repeat] [["hi" "hi" "hi"]] "Create a list of repeated items"]]]]]

[indexed [[spec [[list] [list]]]
          [definition [[count] shield [0] dip 1 range swap zip]]
          [examples [[[[a b c] indexed] [[[0 a] [1 b] [2 c]]] "Index a list"]]]]]

[indexer [[spec [[] [program]]]
          [definition [0 [[generate] dive [[pair] shielddown [inc] dip] bail]]]
          [examples [[[[a b c] [indexer] assemble] [[[0 a] [1 b] [2 c]]] "Index a generator"]]]]]

[indexof [[spec [[item list] [item]]]
          [definition [[indexer] dip
                       ;; use wrap so we can find index of words,
                       ;; otherwise the word gets executed
                       [second wrap =] swap wrap put [[swapdown] dip] inject
                       keep generate first]]
          [examples [[[[[a b c] [take] [c] unwrap indexof] shield] [2] "Get the index of first matching item"]
                     [[[[a b c] [take] [d] unwrap indexof] shield] [[]] "No matching item -> Nothing"]
                     [[[[a b c d c e] [take] [c] unwrap indexof] shield] [2] "Multiple matches returns index of first match"]]]]]

[interpose [[spec [[item ordered] [ordered]]]
            [definition [[] flip
                         [swap pair join [pop] shield] step
                         drop pop drop]]
            [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 [unwrap =] every?] ;; the items at matching indexes are equal
                        [[count] both >=]] ;; the prefix is shorter than the target
                       [execute] every? 
                       dropdown dropdown]] ;; drop the originals
          [examples [[["abcd" "ab" starts?] [yes] "String starts with matching string"]
                     [["abcd" "" starts?] [yes] "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?] [yes] "List starts with matching list"]]]]]

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

[pair [[spec [[item item] [list]]]
       [definition [[wrap] dip put]]
       [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 [[count 2 =] [drop drop []] recover]]
        [examples [[["ab" pair?] [yes] "2-character string is a pair"]
                   [[[a b] pair?] [yes] "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] dip put]]
          [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 [sink pair swap every?]]
        [examples [[[1 2 [odd?] both?] [[]] "Test two items for predicate when not all match"]
                   [[1 3 [odd?] both?] [yes] "Test two items for predicate when all match"]]]]]

[both [[spec [[program [item a] [item b]] [item item]]]
       [definition [[pair] dip step]]
       [examples [[[1 2 [inc] both] [2 3] "Run program on two stack items"]]]]]

[walk [[spec [[[program item-transform] list] [list]]]
       [definition [[list? not] swap
                    [[] swap]
                    [[join] join step wrap]
                    recur unwrap]]
       [examples [[[[1 2 [3 [4 5] 6]] [inc wrap] walk] [[2 3 [4 [5 6] 7]]] "Walk a nested list"]
                  [[[1 2 [3 [4 5] 6]] [clone inc pair] walk] [[1 2 2 3 [3 4 [4 5 5 6] 6 7]]] "Walk a nested list and splice results"]]]]]

; [template [[spec [[[list template]] [list]]]
;            [definition [[snapshot
;                          ;; build a map of word like *1, *2 etc to values on the stack
;                          ;; Do a separate entry for **1, **2, etc which means to splice the value
;                          [count] shield inc 1 1 swapdown range
;                          ["*" "**"] [swap [string join word] map] map
;                          unwrap join dropdown 
;                          [clone [wrap] map swap join] dip swap zip association] dive

;                         ;; save copy of template
;                         [clone] dive

;                         [[swap get] swap prepend wrap
;                          [shield 
;                           [] [dropdown] [drop wrap] if] join
;                          walk] dip
;                         ;; find the highest index placeholder
;                         flatten set 0 swap 
;                         [[word?]
;                          ;; try to parse as a placeholder and get the index
;                          [string ["*" starts?] [take drop] while
;                           [number max] [drop drop] recover] 
;                          [drop] if] step
;                         ;; drop that many items from the stack
;                         [drop] swap float [times] dip]]
;            [examples [[["x" [foo] [bar] unwrap
;                         [*2 [*1 x **2] c d 1 2 3] template]
;                        ["x" [[foo] [bar x foo] c d 1 2 3] ]]]]]]

[flatten [[spec [[list] [list]]]
          [definition [[] swap [list? not] [put] [] [step] recur]]
          [examples [[[[a b [c [d e] f] g] flatten] [[a b c d e f g]] "Flatten a nested list"]]]]]

1.4.1. Associations

[get [[spec [[item sized] [item]]]
      [examples [[[[[a 3] [c 2]] [a] unwrap 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] unwrap 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] unwrap 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 put] "Unassign mixed keylist from nested structure, inner only is promoted to association"]]]]]

[association? [[spec [[item] [boolean]]]
               [examples [[[[[a b] [c d]] association association?] [yes] "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?] [yes] "An empty association is an association"]
                          [[[] [a] 1 assign association?] [yes] "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 =]
                          [yes] "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 [[[lookup] shield] dip ;; m ks v p
                      shielddown
                      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] lookup]
                     [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] [drop drop 10 15] update
                      [a c] lookup]
                     ["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] lookup]
                     [11] "Update function can ignore previous value"]]]]]

[lookup [[spec [[[list keys] sized] [item]]]
         [definition [[something?] ;; keylist not empty
                      [take swap [get] dip] ;; extract the first key and lookup
                      while
                      drop]]
         [examples [[[[[a b] [c d]] association [a] lookup] [[b] unwrap] "Lookup the value of a key in an association"]
                    [[[[a b] [c d]] [a] lookup] [[b] unwrap] "Lookup the value of a key, promoting a list to association"]
                    [[[[a b] [c d]] [e] lookup] [[]] "Looking up a key that doesn't exist returns Nothing"]
                    [[[[outer [[a b] [c d]]]] [outer c] lookup] [[d] unwrap] "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] unwrap]]
                     [[word?] [[word] unwrap]]
                     [[number?] [[number] unwrap]]
                     [[string?] [[string] unwrap]]
                     [[bytes?] [[bytes] unwrap]]
                     [[pipe?] [[pipe] unwrap]]
                     [[error?] [[error] unwrap]]
                     [[environment?] [[environment] unwrap]]
                     [[set?] [[set] unwrap]]
                     [[association?] [[[[type] lookup]
                                       [[count 1 =]
                                        [[first [type] unwrap =]
                                         [first second]
                                         [first first]
                                         if]
                                        [[]]
                                        if]
                                       [[association] unwrap]]
                                      [execute] any?]]
                     [[list?] [[list] unwrap]]]
                    decide dropdown]]
       [examples [[[[[foo 1]] association type] [[foo] unwrap] "An association with one key assumes it is its type"]
                  [[1 type] [[number] unwrap] "Integers are of type number"]
                  [[1.0 type] [[number] unwrap] "Floats are of type number"]
                  [[[] type] [[nothing] unwrap] "Empty list is of type nothing"]
                  [["foo" encode type] [[bytes] unwrap] "A byte array is of type bytes"]
                  [["foo" type] [[string] unwrap] "A string is of type string"]
                  [[[1 2 3] set type] [[set] unwrap] "A set is of type set"]
                  [[[] environment type] [[environment] unwrap] "An environment is of type environment"]
                  [[[[type foo]] association type] [[foo] unwrap] "An association with a single type key, the value is its type"]
                  [[[[type foo] [attr "blah"]] association type] [[foo] unwrap] "An association with a single type key, the value is its type"]
                  [[[[attr1 foo] [attr2 "blah"]] association type] [[association] unwrap] "An association with multiple keys and no type key, is of type association"]
                  [[[[type url] [value "http://foo.com"]] association type] [[url] unwrap] "An association with type/value keys, uses the type key for its type"]]]]]

[value [[spec [[[sized into-association]] [item]]]
        [definition [[count 1 =] ;; if it's a single item
                     [first second] ;; the value is the value of that first item
                     [[value] lookup] ;; otherwise look up the key 'value'
                     if]]
        [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 [[] sink ;; save accumulator below args
                   [[something?] both?] ;; stop when either list is empty
                   [[take] both swapdown pair ;; take from each list and pair them up
                    sink [put] dipdown] ;; put them into the accumulator
                   while
                   drop drop]] ;; 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 [[] swap ;; labels acc
                     [wrap float assign] step]]
        [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"]]]]]

Better zip implementation

[a b c d e] [1 2 3]
[] sink
[swap] [[take] both swapdown pair sink [put] dipdown] while drop drop
[[a 1]
 [b 2]
 [c 3]
 [d []]
 [e []]]
"asd" [\a \b 1] join
[\a \s \d \a \b 1]
[\b \c] "a"  join
"bca"

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?] [yes] "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?] [yes] "List contains a number"]
                       [[[1 2 3 3 5] set 3 contains?] [yes] "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] unwrap \o contains?] [[]] "A word is atomic and doesn't contain anything"]
                       [["food" "foo" contains?] [yes] "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?] [yes] "A list contains another list"]
                       [[[a [b c] d] set [b c] contains?] [yes] "A set contains a list"]
                       [["food" \o contains?] [yes] "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

[[generate [[spec [[program item] [program item]]]
            [definition [clone [execute] dive]]
            [examples [[[1 [inc clone] generate] [2 [inc clone] 2] "Generate a value from state"]]]]]

 [liberate [[spec [[] [program]]]
            [definition [[take]]]]]

 [assemble [[spec [[[program generators] dispenser] [sized]]]
            [definition [[*2 [take] **1 collect] pack shield]]
            [examples [[[[1 2 3 4 5] [[odd?] keep [inc] each] assemble] [[2 4 6]]
                        "Assemble a sequence from a dispenser and a stack of generators"]]]]]

 [prime [[spec [[[program body]
                 [program pred]
                 [program init]]
                [*]]]
         [definition [[clone [execute] dip] dipdown float join while]]
         [examples [[[0 [1 2 3 4] [take] [] [swap [+] dip] prime drop drop] [10]
                     "Prime executes init before each time through the loop"]]]]]


 [into [[spec [[sized program] [list]]]
        [definition [[generate] dip ;; n
                     swap clone ;; n n r
                     [put ;; r
                      [generate] dip ;; r n
                      swap clone]  ;; n n r
                     loop drop]]
        [examples [[[[[\a \b \c \d] [take] "" into] shield]
                    ["abcd"] "Generate into an empty string"]
                   [[[0 10 1 range [take]
                      5 dropper
                      [10 *] each
                      [] into]
                     shield]
                    [[50 60 70 80 90]] "Generate a sequence and put it into the given container"]]]]]

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

 [each [[spec [[program] [program]]]
        [definition [[generate] swap
                     [bail shielddown] decorate
                     join]]
        [examples [[[[1 2 3 4]
                     [[clone *] each]
                     assemble]

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

 [joiner [[spec [[] [program]]]
          [definition [[generate [] swap
                        []
                        [join
                         [generate] dive]
                        while drop]]]
          [examples [[[[[1 2 3] [4 5 6] [7 8 9]]
                       [joiner]
                       assemble]

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

 [taker [[spec [[] [program]]]
         [definition [[[positive?] [dec [generate] dive] [[]] if]]]
         [examples [[[[1 2 3 4 5]
                      [3 taker]
                      assemble]

                     [[1 2 3]]]]]]]

 [catcher [[spec [[] [program]]]
           [definition [[[generate] dive
                         [[[clone] dive execute] bail not]
                         [drop []]
                         when]]]
           [examples [[[[1 2 3 -4 5]
                        [[positive?] catcher]
                        assemble]

                       [[1 2 3]]]]]]]

 [dropper [[spec [[] [program]]]
           [definition [[[[positive?]
                          [[generate drop] dip dec]
                          while
                          [generate swap] dip float]
                         bail]]]
           [examples [[[[1 2 3 4 5]
                        [3 dropper]
                        assemble]

                       [[4 5]]]]]]]

 [skipper [[spec [[] [program]]]
           [definition [[] ;; the state (whether threshold reached)
                        [[] ;; condition - whether we've finished dropping or not
                         [[generate] divedown] ;; true - pass everything else through
                         ;; false - generate, check pred, repeat
                         [[[generate] divedown] ;; prime init
                          [[[clone] divedown execute] bail] ;; bring pred up and exec it
                          [drop] ;; if pred passes drop the value
                          prime ;; after this should have value on top
                          [drop true] dip]
                         if]]]
           [examples [[[[1 2 -3 4 5]
                        [[positive?] skipper]
                        assemble]

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

 [keep [[spec [[program] [program]]]
        [definition [[[[something?] [**1 not]] [execute] every?] pack
                     [clone
                      [[generate] dip ;; pred 1
                       [drop generate]
                       while]
                      dive]]]
        [examples [[[[1 2 3 4 5]
                     [[odd?] keep]
                     assemble]

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

 [group [[spec [[[program group-by]] [association]]]
         [definition [[*1 shield ;; k v state
                       wrap swap  ;;  v k state
                       wrap [put] join update] pack
                      [] association ;; state f
                      swap cram]]
         [examples [[[[[1 2 3 4] liberate [odd?] group] shield]
                     [[[yes [1 3]] [[] [2 4]]] association]]]]]]

 [split [[spec [[sized] [program sized sized]]]
         [definition [[empty] [divedown shield] decorated
                      [[[generate] divedown [clone [put] dip] bail]
                       [[[] [drop swap ends? not]] [execute] every?]
                       [drop] prime
                       drop
                       [swap ends?]
                       [[[count] shield] dive
                        [[count] shield] dive swap - [0] dip slice]
                       when
                       [empty] shield swap]]]
         [examples [[["abcabc" ["b" split] assemble]
                     [["a" "ca" "c"]]]
                    [[[1 2 3 4 2 5] [[2] split] assemble]
                     [[[1] [3 4] [5]]]]]]]]

 [combinations [[spec [[] [program]]]
                [definition [[count] shield -1 ;; l idx i
                             [[[swap count =] dive] [drop drop take 0 swap] when
                              [[wrap lookup] dive [pair] bail] shield [inc] dipdown]]]
                [examples [[[[1 2 3] [combinations] assemble] [[[1 2] [1 3] [2 3]]]]]]]]

 [frequencies [[spec [[] [association]]]
               [definition [[] association
                            [wrap [[] [inc] [1] if] update]
                            cram]]
               [examples [[[["Hello there!" [take] frequencies] shield]
                           [[[\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] dive [] [**1 clone] when] pack
                     ;; generate the first item under the loop body
                     [generate clone] dip
                     loop]]
        [examples [[[[integers 1 dropper 10 taker [+] fold] shield] [55]]]]]]

 [cram [[spec [[[program reducing-function]
                [item initial-value]
                [program generator]] [item]]]
        [definition [[[generate] dive]
                     []
                     float prime drop]]
        [examples [[[[integers 1 dropper 10 taker 0 [+] cram] shield] [55]]]]]]



 [integers [[spec [[] [program]]]
            [definition [-1 [inc clone]]]]]]
join
;; partition
[[] [program]] ;; the spec
;; construct the dynamic definition for partition

[[take-chunk [[taker collect
               dropdown dropdown] ; drop the used-up taker generator
              join divedeep]]
 [shift [[[count <=]
          [swap 0 slice]
          [[]] if] shield swap]]]
[[]
 [over wrap take-chunk [join shift] bail]
 [[over] dive wrap take-chunk swap drop shift]
 if] let 
;; add an empty list for the partition state
[[]] swap put ;; the definition

[[[[1 2 3 4 5 6 7] [2 2 partition] assemble]
  [[[1 2] [3 4] [5 6] [7]]]]] ;; examples

[examples definition spec] label [partition] swap assign
[[pairwise [[spec [[program] [*]]]
            [definition [[[] evert ;; capture stack
                          [2 2 partition] assemble] dip ;; pair up stack items
                         inject ;; run the program on the pairs
                         [joiner] assemble ;; unpair the items
                         unwrap [] swap evert drop]] ;; restore as the stack
            [examples [[[1 2 3 4 5 [swap] pairwise] [1 4 5 2 3]]
                       [[1 2 3 4 5 [float] pairwise] [2 3 4 5 1]]
                       [[1 2 3 4 5 [[[+] inject] both] pairwise] [1 5 9]]]]]]]
join
[[] [program]] ;; the spec
;; construct the dynamic definition for partition

[[take-chunk [[taker collect
               dropdown dropdown] ; drop the used-up taker generator
              join divedeep]]
 [shift [[[count <=]
          [swap 0 slice]
          [[]] if] shield swap]]]
[[]
 [over wrap take-chunk [join shift] bail]
 [[over] dive wrap take-chunk swap drop shift]
 if]

[draft dictionary swap [emit encode hashbytes] shield
 [[[words] swap update] shield dropdown] dip
 sink [dictmerge] shielddeep] dip
float wrap [put] join
swapdown [modules] swap update
;; TODO try using confine here
[*1 *2 confine] pack
join dump


[[[] [program] [[modules [#b64 "yO3LwN0ITlhqAj8T1IKcUqNoiQmEAyrBwbFpGixDtQ8"]]
                [words 249_entries]]
  [[] [over wrap take-chunk [join shift]
       bail]
   [[over] dive wrap take-chunk swap drop shift]
   if]
  confine]
 247_entries [words] [[modules []]
                      [words 247_entries]]]

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 =] [yes]]
                       [["foo" encode hashbytes
                         "fop" encode hashbytes
                         =]
                        [[]]]]]]]

[resolve [[spec [[word] [word]]]]]

[dictmerge [[spec [[[dictionary module] [dictionary original] [bytes hash]] [dictionary]]]]]
[updates [[spec [[[sized word-updates]] [[program single-update]]]]
          [definition [[[take]
                        [[0] [wrap] update ;; wrap the word name to get a path to update
                         [update] join] each
                        joiner generate] shielddown]]]]

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

[words [[spec [[] [association]]]
        [definition [dictionary [words] lookup]]]]

[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 execute]] ;; install the module in the dictionary
                        [execute] map ;; fork 
                        dropdown unwrap swapdown dictmerge]]]]

[draft [[spec [[[sized definitions]] [[program dictionary-updater]]]]
        [definition [[[1] [entry] update] map ;; create full entries for each definition
                     wrap [join] join]]]]  ;; add 'join' to join the entries with the existing dictionary

[let [[spec [[program [sized entries]] [*]]]
      [definition [[draft dictionary swap [emit encode hashbytes] shield
                    [[[words] swap update] shield dropdown] dip
                    sink [dictmerge] shielddeep] dip
                   float wrap [put] join
                   swapdown [modules] swap update
                   [dictionary program] label environment
                   ;; TODO try using confine here
                   [*1 capture evaluate [stack] lookup restore] pack]] 
      [examples [[[[[times5 [5 *]]
                    [doubledec [dec dec]]]
                   [3 times5 doubledec] let execute] [13]]
                 [[[[swap [5]]]
                   ["a" "b" "c" swap]
                   let execute]
                  ["a" "b" "c" 5]]
                 [[[[foo ["outer"]]]
                   ["inner"] let
                   [foo] label
                   [foo] let execute] ["inner"]]]]]]

[definition [[spec [[list] [program]]]
             [definition [[words **1 definition] pack dictionary swap lookup]]
             [examples [[[1 2 3 [flip] definition execute] [3 2 1] "Fetch the definition of a word and use it"]]]]]
[[plus2 [2 +]]]
[5 plus2]
[draft dictionary swap [emit encode hashbytes] shield
 [[[entries] swap update] shield dropdown] dip
 sink [dictmerge] shielddeep ] dip
float wrap [put] join
swapdown [modules] swap update 
[dictionary program] label environment
wrap [[snapshot] dive ;; grab a snapshot 
     [stack] swap assign ;; set the env's stack to that value
      evaluate
      [stack] lookup restore] ;; promote the result
join 
execute
;[0 dictionary entries] lookup [first [plus2] unwrap =] filter inspect
7
"foo" "bar"
[[foop [3 * plus2]]
 [plus2 [2 +]]]
[5 foop]
[draft dictionary swap [emit encode hashbytes] shield
 [shield] dip
 sink [dictmerge] shielddeep] dip ;; under the let program ;; prog dict hash
[wrap] dipdown ;; wrap the hash to make a list of 1 namespace

[program dictionary] label environment swap pair ;; creates closure
;; when the closure executes, capture the outer stack first
[[[stack] [snapshot] divedown assign] dip using evaluate [stack] lookup restore] join execute
;wrap  [[stack] [snapshot] divedown assign evaluate [stack] lookup restore] join ; execute

[a b c d e] [take] 2 2 []


[[take-chunk [[taker collect
               dropdown dropdown] ; drop the used-up taker generator
              join divedeep]]
 [shift [[[count <=]
          [swap 0 slice]
          [[]] if] shield swap]]]
[[]
 [over wrap take-chunk [join shift] bail]
 [[over] dive wrap take-chunk swap drop shift]
 if] let
;; add an empty list for the partition state
;[[]] swap put

collect
[[a b]
 [c d]
 [e]]
[[[dictionary dictionary_redacted]
  [program [[] [over wrap take-chunk [join shift]
                bail]
            [[over] dive wrap take-chunk swap drop shift]
            if]]
  [resolver [#b64 "yO3LwN0ITlhqAj8T1IKcUqNoiQmEAyrBwbFpGixDtQ8="]]]
 [stack] [snapshot] divedown assign environment evaluate [stack] lookup restore]
[] 2 2 [take] []
[a b c d e] 2 
[a b]
[[take-chunk [[taker collect
                 dropdown dropdown] ; drop the used-up taker generator
                join divedeep]]
   [shift [[[count <=]
            [swap 0 slice]
            [[]] if] shield swap]]]
  [[]
   [over wrap take-chunk [join shift] bail]
   [[over] dive wrap take-chunk swap drop shift]
   if] let

partition dropdown  [first [dictionary] lookup [first] map set] both
[* + - / < <= = > >= abs addmethod and animate any? assert assign association association?
 attend autoformat
 bail bits both both? branch butlast bytes? cache ceiling clone clonedeep clonedown
 close compare confine contains? count cut database days
 dec decache decide decodejson decorate decorated definition dictionary dictmerge
 dip dipdeep dipdown dive divedeep divedown draft drop dropdeep dropdown emit
 empty empty? encode encodejson encodenumber encodestring ends? entry environment
 error? eval-step evaluate even? evert every? execute exp fail file-in file-out
 filter finished? first flatten flip float floor format future generator get handle
 handoff hashbytes hours if inc indexed indexer indexof
 inject inscribe inspect interpose intersection join label last let list? log lookup
 loop map max method? milliseconds min minutes mod
 module negative? not number number? odd? or over pad pair pair? persist pipe-in pipe-out
 pipe? pop positive? prepend prime primrec
 print put quot radix range read receiver recover recur rem repeat rest restore retry
 reverse round second seconds select sender
 serversocket set set? shield shielddeep shielddown shift sink siphon sleep slice
 slurp snapshot socket something? sort sort-indexed spawn spit sqrt
 stage standard starts? step string string? swap swapdown take take-chunk template
 timer times timestamps toe tos triplet tunnel type unassign
 under until unwrap update updates using value walk when while within? word word?
 wrap xor yes zero? zip]
[* + - / < <= = > >= abs addmethod advance and animate any? assemble assert assign
 association association?
 attend autoformat bail bits both both? branch break breakpoint butlast bytes? cache
 catcher ceiling clone clonedeep clonedown close collect combinations
 compare confine contains? count cram cut database days dec decache decide decodejson
 decorate decorated definition dictionary dictmerge dip dipdeep dipdown
 dive divedeep divedown draft drop dropdeep dropdown dropper dump each emit empty
 empty? encode encodejson encodenumber encodestring ends? entry environment
 error? eval-step evaluate even? evert every? execute exp fail file-in file-out filter
 finished? first flatten flip float floor fold format
 frequencies future generate generator get group handle handoff hashbytes heatmap
 hours if inc indexed indexer indexof inject inscribe inspect integers
 interpose intersection into join joiner keep label last let liberate list? log lookup
 loop map max method? milliseconds min minutes
 mod module negative? not number number? odd? or over pad pair pair? pairwise partition
 persist pipe-in pipe-out pipe? pop positive?
 prepend prime primrec print put quot radix range read receiver recover recur rem
 repeat rest restore retry reverse round second
 seconds select sender serversocket set set? shield shielddeep shielddown shift sink
 siphon skipper sleep slice slurp snapshot socket something? sort
 sort-indexed spawn spit split sprint sqrt stage standard starts? step stepper string
 string? swap swapdown take take-chunk taker template timer
 times timestamps toe tos tracer triplet tunnel type unassign under until unwrap update
 updates using value walk when while within?
 word word? wrap xor yes zero? zip]

1.6. Math

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

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

[* [[spec [[number number] [number]]]
    [examples [[[4 3 *] [12]]
               [[10 1.5 * 15 0.0001 within?] [yes]]
               [[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] lookup] [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]]]]]]

[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?] [yes]]
                  [[-1 odd?] [yes]]
                  [[4 odd?] [[]]]]]]]

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

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

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

[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] dip <]]
          [examples [[[1.0 2.0 + 3 0.001 within?] [yes]]]]]]

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"]]]]]]

[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

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

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

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

[not [[spec [[item] [boolean]]]
      [examples [[[1 even? not] [yes]]
                 [[[] not] [yes]]
                 [[yes not] [[]]]
                 [[[] not] [yes]]]]]]

1.9. Byte encoding and decoding

[encodestring [[spec [[string] [bytes]]]
               [examples [
                [["foo" encodestring] [#b64 "Zm9v"]]
                [["" encodestring] [#b64 ""]]]]]]

[encodenumber [[spec [[number] [bytes]]]
               [examples [[[12 encodenumber] [#b64 "AAAAAAAAAAw"]]
                          [[12.3 encodenumber] [#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?] [yes]]
                    [[[#b64 "Zm9v"] bytes?] [[]]]
                    [["foo" encode bytes?] [yes]]]]]]

[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 joiner] assemble unwrap]]
       [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 [[[[bytes?] []]
                        [[string?] [encodestring]]
                        [[number?] [encodenumber]]
                        [[true] [emit encode]]]
                       decide]]
          [examples [[[12 encode] [#b64 "AAAAAAAAAAw"]]
                     [["foo" encode] [#b64 "Zm9v"]]
                     [["foo" encode encode] [#b64 "Zm9v"]]
                     [["" encode] [#b64 ""]]]]]]

 [radix [[spec [[integer integer] [list]]]
         [definition [[[/] shield swap
                       [*] shielddown
                       swapdown -
                       swap [prepend] dip]
                      swap prepend
                      [[] swap [positive?]] dip
                      while drop]]
         [examples [[[7 2 radix] [[1 1 1]]]
                    [[9 3 radix] [[1 0 0]]]
                    [[255 16 radix] [[15 15]]]]]]]]
join

1.10. Strings

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

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

[string? [[spec [[item] [boolean]]]
          [examples [[["hi" string?] [yes]]
                     [["" string?] [yes]]
                     [[["hi"] string?] [[]]]
                     [[yes string?] [[]]]]]]]

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

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

[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 [snapshot ;; save stack to print in err message
                       [shield] dive ;; run the assertion under the saved stack
                       [drop] ;; if passes, drop the saved stack, dont need
                       [string ["assertion failed "] dip join fail] ;; else throw err
                       branch]]]]

 [recover [[spec [[program program] [*]]]
           [definition [[[handle] join] dip ;; add handle to the end of test
                        [snapshot] dipdown ;; rec test ss
                        sink inject ;; res rec
                        [first error?] ;; err? res rec
                        [first swap execute];; drop the snapshot and run recovery
                        [evert drop] ;; use snapshot as stack
                        if]]
           [examples [[[[+]
                        [drop 1
                         [+] [drop 2 +]
                         recover]
                        recover]
                       [3]]

                      [[[1 2 "oh fudge"]
                        [[5 +]
                         [drop 5]
                         recover]
                        map]
                       [[6 7 5]]]

                      [[[swap] [drop swap] recover]
                       [swap]]]]]]

 [retry [[spec [[error] [*]]]
         [definition [[unwound] lookup
                      execute]]
         [examples [[[2 3 "four" * + handle [drop 4] dip retry] [14]]]]]]]
join

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] pack
                          [0] swap update]]
             [examples [[[[[[[count 3 >] ["foo" put]]
                            [[not] ["bar" put]]] decide]
                          [count 1 =] [rest] addmethod]

                         [[[[[count 1 =] [rest]]
                            [[count 3 >] ["foo" put]]
                            [[not] ["bar" put]]]
                           decide]]]]]]]

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

1.13. Database

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

[[fork [[execute] map]]
 [triangle [[[] [[take] dip swap [[put] shield sink swap pair] bail] collect] shielddown]]
 [indexed-as-property [swap indexed
                       [unwrap sink assign] map dropdown]]
 [join-all [[first empty] shield swap [join] step]]
 [selectkeys [set [*1 [first] dive contains?] pack filter]]
 [invert [[reverse] map association]]

 ;; datalog variables
 [variable? [[[word?]
              [string last \? =]] [execute] every?]]
 [variable= [[[pair [variable?] every?] [=]] [execute] every?]] 

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

 ;; links between datalog constraints
 [links [slot-combos
         [[wrap] map unwrap swapdown 
          [[[lookup] inject] both] pairwise 
          variable=]
         filter    
         [unwrap pair sink pair
          [[index] lookup] map swap zip]
         map]]
 [all-links [[] sink
             [[[[index] lookup] shield] both ;; lookup the indices of both constraints
              [swapdown] dip sink ;; move the indices under the constraints
              [links] shielddown
              swap [dropdown dropdown join] dip] 

             step drop]]
 [format-link [[join] inject unwrap [string] map
               "c{0}.{1} = c{2}.{3}" swap format]] 

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

 ;; where clause data processing
 [where-data [[[index] lookup] shield swap 
              [[[second variable? not]
                [first [index] unwrap = not]] [execute] every?] filter 
              [swap prepend] map dropdown]]
 [format-where [[string] map 
                "c{0}.{1} = :c{0}{1}" swap format]]
 [make-where [first [where] lookup anded-together]]
 [format-join [[[[on] lookup]
                [[where] lookup]
                [[index] lookup string]] [execute] map
               [join anded-together] inject 
               "JOIN EAV c{1} ON {0}" swap format]]
 [make-query [rest [[on]
                    [[format-link] map] update
                    [format-join] shield [join] swap assign] map]]

 ;; SQL parameters for rusqlite
 [param-name [[string] map ":c{0}{1}" swap format]]
 [extract-params [[] association swap [[params] lookup join] step]]


 ;; SELECT clause
 [wordval? [second word?]]
 [invert [[reverse] map association]]
 [validate [[[second not]
             [first "All selected query variables must appear somewhere in constraints"
              [reason variable] label fail]
             when] map]]
 [select-data [swap
               [[slots selectkeys invert] shield
                [wordval?] filter join association] map
               swap
               [[[[index *1] selectkeys] pack ;; make the program to cut down 
                 map 
                 [count 2 =] filter first [second] map
                 [first number?] [reverse] when] ;; items are in random order due to coming from association, fix the order
                map]
               shield dropdeep zip
               validate]]

 ;; query 
 [extract-data [[[[unwrap all-links]
                  [first where-data   ; [join] inject unwrap
                   ;; build the query param map
                   [[[] swap
                     [[param-name] shield [last] dip wrap swap assign]
                     step]
                    ;; build the actual query where clauses
                    [[format-where] map]]
                   fork]]
                 fork] shield
                ;; combine extracted items

                [first] dip ;; keep the original constraint to add properties to
                unwrap unwrap [where params on] label join]]
 [format-select [[unwrap swap
                  string butlast ;; remove the ? from the variable name for result column
                  put
                  [string] map
                  "c{1}.{0} as {2}" swap format] map ", " interpose join-all]]]

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

[swap
 ;; expand all combinations of constraints
 [constraint] map
 ;;[] 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] map
 [[extract-params]
  [make-query]
  [make-where]
  [swap select-data]] fork 
 dropdown ;; don't need original anymore
 unwrap float
 [[join] lookup] map  
 swap format-select 
 [" " interpose join-all] dip triplet reverse
 "SELECT {0} from EAV as c0 {1} WHERE {2}" swap format
 swap dropdeep]

let
[definition spec] label
[query] swap assign

1.14. Pipes

[pipe? [[spec [[item] [boolean]]]
        [examples [[[timestamps pipe?] [yes]]
                   [[standard pipe?] [yes]]
                   [[[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] unwrap =]
                          [value file-in]]
                         [[type [stdout] unwrap =]
                          [stdout]]]
                        decide]]]]

 [tunnel [[spec [[item] [pipe]]]
          [definition [association
                       [[[type [ip-host] unwrap =]
                         [clone
                          [port] lookup
                          [[address] lookup] dip
                          serversocket]]
                        [[type [ip-client] unwrap =]
                         [clone
                          [port] lookup
                          [[address] lookup] dip
                          socket]]]
                       decide]]]]

 [pipe-out [[spec [[item] [pipe]]]
            [definition [association
                         [[[type [file] unwrap =]
                           [value file-out]]
                          [[type [ip-host] unwrap =]
                           [clone
                            [port] lookup
                            [[address] lookup] dip
                            serversocket]]]
                         decide]]]]

 [spit [[spec [[item [item target]] []]]
        [definition [[pipe-in] dip encode put drop]]]]

 [slurp [[spec [[pipe] [item]]]
         [definition [[take] [join] fold string [drop drop] dip]]]]

 [print [[spec [[string] []]]
         [definition [[standard] dip "\n" join encode put drop]]]]

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

 [sleep [[spec [[integer] []]]
         [definition [timer take drop drop]]]]

 [future [[spec [[program] [pipe]]]
          [definition [handoff swap
                       [[**1 snapshot] ;; return entire stack
                        dive put drop] pack
                       dictionary swap spawn animate]]
          [examples [[[1 [2 +] future take dropdown] [1 [3]]]]]]]

 [generator [[spec [[[program generator-maker]] [[program wrapped-generator]]]]
             [definition [[] swap inject
                          [[generate] inject take]]]]]  ;; generate from the wrapped generator

 [siphon [[spec [[[receptacle output] [program generator]] [[receptacle output]]]]
          [description "Generates values from a wrapped generator (stacked generator inside a list), until exhausted, puts all items into the output receptacle"]
          [definition [[] ;; placeholder that gets dropped (next
                       ;; iteration it will hold a copy of the last
                       ;; element which is only needed to check if
                       ;; the loop continues and can be dropped
                       ;; after)
                       [empty?] ;; stop when generator returns
                       ;; nothing
                       [drop ;; the last value
                        [generate clone] dip
                        sink
                        [[put] bail] dip]
                       until
                       drop drop sink drop drop]] ;; the now-empty dispenser
          [examples [[[[[integers 5 taker] generator [] siphon] shield] [[0 1 2 3 4]]]]]]]

 [close [[spec [[pipe] []]]
         [definition [drop]]]]]
join

1.15. Crypto

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

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

[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] shield verify] [yes]]]]]]
[[delegated [[spec [[[association pubkey]] [program]]]
             [definition [[[sink ;; css cs pk
                            [[hash] [shield dip] decorated ;; css csh cs pk
                             float ;; cs css csh pk
                             [verify] dip
                             [[]]  ;; the program to run if the child script isn't authorized
                             branch] ;; runs the child script if the sig on its hash is verified
                            [drop drop ;; the sig and (empty) child script -> pk sig msg
                             sink ;; sig msg pk
                             verify]
                            [clone] dipdown branch]
                           [[]] recover]
                          swap prepend]]]] ;; prepend the pubkey

 [hash [[spec [[item] [bytes]]]
        [definition [[[[bytes?] [hashbytes]]
                      [[true] [encode hash]]]
                     decide]]]]]
join

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 *]]]]]
join

1.17. Nested Environments

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

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

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

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

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

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

[use [[spec [[[program [list modules]] [*]]]]
      [definition [[program] label environment swap ;; lm env
                   [[stack] [snapshot] divedown assign] dip ;; capture the stack at runtime
                   using ;; set up the resolver 
                   evaluate ;; execute the program in the inner environment
                   [stack] lookup restore ;; replace the stack with the result from the inner env
                   ]]]]
[tos [[spec [[environment] [item]]]
      [definition [[stack] lookup first]]
      [examples [[[[[stack [1 2 3]]
                    [program [[+] step]]]
                   tos]
                  [1]]]]]]

[top [[spec [[environment] [item]]]
      [definition [[program] lookup first]]
      [examples [[[[[stack [1 2 3]]
                    [program [[+] step]]]
                   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]
                       [snapshot] divedown
                       assign]]]]

[spawn [[spec [[program dictionary] [environment]]]
        [definition [[snapshot] dipdown ;; p d s
                     [program dictionary stack] label
                     environment]]
        [examples [[[1 2 3 dictionary [swap clone] spawn]
                    [1 2 3 [[program [swap clone]] [stack [3 2 1]]] environment]]]]]]

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

1.17.1. Debugging

[[break [[spec [[[program condition] environment]
                [[program condition] environment]]]
         [definition [[[[swap something?] ;; still running
                        [execute not]] ;; check condition not true yet
                       [execute]
                       every?] ;; break?
                      [[eval-step] dip]  ;; evaluate the environment one step
                      while]]]]

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

 [sprint [[spec [[environment]
                 [environment]]]
          [definition [[[program 0] lookup wrap [breakpoint] =] break
                       drop ;; the condition
                       [] [eval-step] when]]]] ;; advance past the breakpoint word if the program isn't complete


 [advance [[spec [[environment] [environment]]]
           [definition [[[program] lookup count] shield swap ;; count up the program length, we'll run until it's smaller than this

                        [[program] lookup count  ;; only stop if expr empty or shorter than we started off
                         [[positive?] [<=]] [execute] every?]
                        [eval-step]  ;; evaluate the environment one step
                        while
                        dropdown]]]]  ;; drop the program length item

 [stepper [[spec [[] [program]]]
           [definition [[eval-step clone]]]]]

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

 [dump [[spec [[] []]]
        [definition [snapshot wrap emit autoformat print]]]]

 [heatmap [[spec [[program] [association]]]
           [definition [[tracer
                         ;; what item is being executed
                         [[program] lookup [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] shielddown]]]]]


join
[[evaluating? [[program] lookup [evaluate] starts?]]
 [with-innermost [[[] swap
                   [[evaluating?]
                    [[stack 0] clone [lookup] dip swap [join] dip ] ;; append the next part of the path to the accumulator
                    while swap] shield dropdeep]
                  dip ;; under the stepping prog
                  [update] shielddown flip drop

                  ;; find which envs are finished and remove
                  ;; 'evaluate' from parent
                  [0 -2 slice clone] [collect] shielddeep 
                  [[[[[evaluating?]
                      [[stack 0] lookup finished?]]
                     [execute] every?]
                    [[program] [rest] update]
                    when]
                   [update] shielddown flip drop drop]
                  step]]]
join
1.17.1.1. Examples
  1. Count the number of times each word is executed while running a program.
    [[program [10 [0 >] [clone dec] while]]]  ;; the sample program to run
    environment
    evaluate
    
    [[stack [0 1 2 3 4 5 6 7 8 9 10]] [program []]]
    
    10 [0 >] [clone dec] while
    
    
    [0 1 2 3 4 5 6 7 8 9 10]
    
    [swap] unwrap  word?
    
    
    [yes]
    

    "Increment the counter, or set to 1 if nothing"

    [] [inc] bail 1 or
    
    1
    
    [] ;; empty list to put word counts in
    [[program [3 [0 >] [clone dec] while]]]  ;; the sample program to run
    environment
    [[program] lookup something?] ;; something still in the program, keep running
    [[[program] lookup first] shield ;; get the item we're about to execute
     swap ;; put it under the environment
     [[word?] ; if it's a word
      [wrap
       [[inc] bail 1 or]
       update] ;; the results, the count for the word about to execute
      [drop] ;; if it's not a word, do nothing
      if] dip
     eval-step] ;; evaluate the environment one step
    while
    drop ;; drop the environment and just report the word counts
    
    [[wrap 1] [step 2] [first 4] [snapshot 4] [execute 1] [put 1] [inject 4] [loop 4] [dec 3] [decorate 1] [swap 5] [unwrap 14] [take 4] [join 1] [> 4] [while 1] [shield 4] [dipdown 1] [evert 16] [clone 8] [dip 9]]
    

    Now that we have generators and frequencies I think this can be greatly simplified:

    [5000 [0 >] [clone dec] while]  ;; the sample program to run
    tracer
    [[program 0] lookup "foo" or] each
    [word?] keep
    frequencies
    
    [[> 1001]
     [clone 2002]
     [dec 1000]
     [decorate 2]
     [decorated 1]
     [dip 2007]
     [dip 2]
     [dipdown 1]
     [evert 4004]
     [execute 1]
     [first 1001]
     [inject 1001]
     [join 1]
     [loop 1001]
     [put 3]
     [shield 1001]
     [shield 1]
     [snapshot 1001]
     [step 5]
     [swap 1002]
     
     [take 1001]
     [unwrap 1001]
     [while 1]
     [wrap 3]]
    [clone [[generate] dip [drop generate]
            while]
     dive]
    [[[something?] [word? not]]
     [execute] every?]
    [generate [[[program 0]
                lookup "foo" or]
               bail]
     shielddown]
    [eval-step clone]
    []
    
  2. CANCELED spec checking

    clojure spec check can be replaced with predicate programs, that will be run with shield before the actual word and if it returns false, will raise an error.

  3. TODO Trace output
    [] ;; results
    [[program [1 [2 3 4 5] [*] step]]]  ;; the sample program to run
    environment
    
    [[program] lookup something?] ;; break?
    [eval-step clone [put] dip]  ;; evaluate the environment one step
    while
    
    
    [[[stack [120]] [program []]]
     [[[stack [1]] [program [[2 3 4 5] [*] step]]]
      [[stack [[2 3 4 5] 1]] [program [[*] step]]]
      [[stack [[*] [2 3 4 5] 1]] [program [step]]]
      [[stack [[*] 2 1]] [program [execute [3 4 5] [*] step]]]
      [[stack [2 1]] [program [* [3 4 5] [*] step]]]
      [[stack [2]] [program [[3 4 5] [*] step]]]
      [[stack [[3 4 5] 2]] [program [[*] step]]]
      [[stack [[*] [3 4 5] 2]] [program [step]]]
      [[stack [[*] 3 2]] [program [execute [4 5] [*] step]]]
      [[stack [3 2]] [program [* [4 5] [*] step]]]
      [[stack [6]] [program [[4 5] [*] step]]]
      [[stack [[4 5] 6]] [program [[*] step]]]
      [[stack [[*] [4 5] 6]] [program [step]]]
      [[stack [[*] 4 6]] [program [execute [5] [*] step]]]
      [[stack [4 6]] [program [* [5] [*] step]]]
      [[stack [24]] [program [[5] [*] step]]]
      [[stack [[5] 24]] [program [[*] step]]]
      [[stack [[*] [5] 24]] [program [step]]]
      [[stack [[*] 5 24]] [program [execute]]]
      [[stack [5 24]] [program [*]]]
      [[stack [120]] [program []]]]]
    
  4. DONE Step count limiting

    When testing or debugging, limit the number of steps to avoid a possible infinite loop.

    200 ;; step count remaining
    [[program [10 [0 >] [clone dec] while]]]  ;; the sample program to run
    environment
    
    [[program] lookup something? ;; something still in the program
     [positive?] dip and] ;; still step budget remaining
    [eval-step ;; evaluate the environment one step
     [dec] dip] ;; decrease the step budget
    while
    
    ;[stack] lookup ;; return the output
    
    [[program [take dip evert first [clone dec [0 >] shield] loop]] [stack [[[0 >] 4 5 6 7 8 9 10] 4 5 6 7 8 9 10]]] 0
    
  5. DONE Breakpoint
    [[[[toe [+] unwrap =]
       [tos 3 >]]
      [execute]
      every?] ;; when to stop - when we're about to add and tos already >3
     [0 [1 2 3 4 5] [+] step]  ;; the sample program to run
     environment
    
     [[[[program] lookup something?] ;; something still in the program
       [swap execute not]] ;; don't stop yet
      [execute]
      every?] ;; break?
     [eval-step]  ;; evaluate the environment one step
     while]
    
  6. TODO Step over
    [[0 [1 2 3 4 5] [+] step]  ;; the sample program to run
     environment
    
    [[program] lookup count] shield swap;; count up the program length, we'll run until it's smaller than this
    
     [[program] lookup count
      [[positive?] [<=]] [execute] every?] ;; only stop if expr empty or shorter than we started off
     [eval-step]  ;; evaluate the environment one step
     while]
    

1.18. TODO Functional environment

There are use cases for kcats where you don't want a program to be able to mess with external resources like files, network sockets etc nor be able to spawn new threads, the program it's running should be a pure function and this module lets you enforce that.

[pipe-in pipe-out channel timeout
 handoff file-in file-out timestamps
 standard serversocket animate future
 spit tunnel database]
[wrap unassign] step

2. Issues

2.1. DONE Get rid of platform-specific definitions

2.2. DONE fix evaluate

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

[[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] dip get]]
 [addchild [[pop] dip put put]]
 [rawpath [1 [interpose] shield swap prepend dropdown]]
 [siblings [[] node sink [addchild] dip addchild]]
 ;[path [[] [take swap [child] dip path] [drop] if]]
 [path [dec 2 radix rawpath]]
 [parent [butlast butlast]]
 [rehash [[children [data] map] shield
          [first] shield empty swap [join] step
          hash wrap [0] swap update]]
 ;; lopsidedtree n
 [balance []]
 ;; node tree cur-ct
 [add [[clone path [pop zero?] [parent] when] dipdown  ;; node tree path ct
       swapdown ;; 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 swap put dropdown lookup
;  "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] [] if
;  ;dump
;  ["quux" hash node siblings rehash ] update
; ]
[["foo" "bar" "baz" "quux"] [node] map []
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] shield swap prepend 0 put dropdown [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] [drop drop "hi" "there"] update
["foobarbaz" [["foobar" [["foo" []]
                         ["bar" []]]]
              "there"]]
[[hash []]
 [children [second]]
 [data [first]]
 [node [[] pair]]
 [child [[children] dip get]]
 [addchild [[pop] dip put put]]
 [siblings [[] node sink [addchild] dip addchild]]
 ;[path [[] [take swap [child] dip path] [drop] if]]
 [path [dec 2 radix nodepath]]
 [rehash [[children [data] map] shield [first] shield empty swap [join] step hash wrap [0] swap 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] dip put put]]
 [siblings [[] node sink [addchild] dip addchild]]
 [nodepath [1 [interpose] shield swap prepend dropdown]]
 [padded [[[[count] shield] dive -] dip
          swap repeat
          swap join]]
 [path [[dec 2 radix] dip 2 log ceiling 0 padded nodepath]] ;; item-ct index
 [depth []]

 [rehash [[children [data] map] shield
          [first] shield empty swap
          [join] step
          hash
          wrap [0] swap update]]
 [joiner [[2 2 partition
           [[count 1 =] [[] put] when
            unwrap siblings] each]
          assemble [rehash] map]]
 [merkle [[hash node] map
          [count 1 >] [joiner] while]]]
[["a" "b" "c" "d" "e"]
 count
 5 ;; 2nd item
 swap 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 [[[count] shield] dive -] dip
        swap repeat
        swap 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] [take]
3
[[[positive?]
  [[generate drop] dip dec]
  while
  [generate swap] dip float]
 bail]
collect
[4 5]
[[[positive?] [[generate drop]
               dip dec]
  while [generate swap]
  dip float]
 bail]
0 [take] []

This is what drop-while looks like

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

Author: Skyrod Vactai

Created: 2024-10-16 Wed 14:22

Validate