# ck: array operations in joy

## sa@dfa.com — 2003-05-16 17:30:17

    hi all

    this must be the week for implementing joy - here's another one.

         http://www.nsl.com/papers/ck.htm         <- doc

         http://www.nsl.com/k/ck.k                <- code

    i've been thinking about this on and off for a couple of years.

    ck is my second go at the problem.

    in this version, i try to stay faithful to manfred's notational

    decisions:  [] for lists, / for division, 'x for characters, &c.

    no sets, no arithmetic on characters or strings, and the i/o

    options and interpreter controls are different.

    ck is written entirely in k - about 275 lines of commented code,

    most of which are one-liners for the numerous joy primitives.

    for example, here is the integer version of the primrec combinator:

         s3[{[s;i;b;r]:[i;E[_f[s,i;i-1;b;r];r];E[s;b]]}]

    takes the stack s, an int i, programs b and r.  if i is non-zero,

    evaluate (E) r on the result of recursing (_f) with i decremented.

    else evaluate b.  of course, i'm always amazed when something like

    this actually works.

    of course the k list semantics (atomic extension) is built-in:

         [1 2 3]+[4 5 6]

       [5 7 9]

    and all the k primitives are where they're supposed to be - namely,

    on the ascii symbols.  there are 20 x 2 of them, plus / for integer

    division (which is not a k primitive).

    the k adverbs (which are really combinators) are on keywords:

    each, prior, right, left, over, do, while, converge, &c.

    one thing i haven't implemented is joy-style definition.  for

         add2 == 2 +

    ck has

         [2 +] `add2 def

    def is really assignment, which means that ck isn't purely

    functional, but then neither is k.

    another deviation, this time from concatenativity:  function-maps

    with named parameters (`abc is a k symbol - an atomic string).

         {[`a`b`c] [a b +] [a c +] *}

    which is syntactic sugar for:

         [[`a`b`c] [a b +] [a c +] *] m

    it seems like it shouldn't be too hard to take the pattern and body

    of an m-list and produce a list which is computationally equivalent

    to the m-list but which has no named parameters.  i think brent

    gives (or alludes to) an algorithm in his "theory" paper.

    error-checking is minimal, but the stack is guaranteed to be

    "safe":  the primitives return only k objects, and the stack

    is just a list of k objects.  if execution fails, you just

    signal back to the interpreter and continue on.

    a ck application:

    \ life in ck;

    [[0 0 0 0 0]

     [0 0 0 1 0]

     [0 1 1 0 0]

     [0 0 0 1 0]

     [0 0 0 0 0]]            `rpent set           \ r pentomino;

    [1 swap !]                    `l def          \ left shift;

    [-1 swap !]                   `r def          \ right shift;

    [[[[r] map r]

      [[r] map l]

      [[l] map r]

      [[l] map l]

      [[l] map  ]

      [[r] map  ]

      [r        ]

      [l]       ] [i] right]      `adj def        \ adjacencies;

    [dup adj

     [+] over dup

     3 = swap dup

     2 = & |]                     `next def       \ next generation;

    [next dup " *" of sysout;]    `go def         \ next, output;

    rpent 5 [go] do                               \ five generations;