a k3 implementation of k4 select, update, and eval ================================================== select and update ----------------- k4 contains two powerful primitives for table selection and update, both with and without aggregation: ?[t;c;b;a] / select by from where ![t;c;b;a] / update by from where t is a table. c is a list of parse-trees of row-constraints. b is a vector of grouping columns. a is a dictionary of parse-trees of column-calculations. for example, the k4 q-expression: d:select p:sum i,q:sum i+1,r:avg i,s:sum i+j by f,g from t where f=`c,g in 2 3 4,h>.5 can be coded in k3 this way: c:((=;`f;,`c);(_lin;`g;2 3 4);(>;`h;.5)) b:`f`g a:.+(`p`q`r`s;((+/;`i);(+/;(+;`i;1));({(+/x)%#x};`i);(+/;(+;`i;`j)))) d:select[t;c;b;a] where t is a table with columns f, g, h, i, and j. parse-tree structure -------------------- row-constraints: c is a list (c1;..;cn) which means: c1 & .. & cn, i.e. &&/eval'c. column-calculations: a is a dictionary where each column !a will be assigned the result of evaluating each a[]. parse-trees are evaluated recursively: (f;a1;..;an) means: apply n-adic function or symbol f to arguments a1 .. an. atomic symbols are interpreted as columns of the table t being operated on: (=;`f;10) means: t[`f] = 10. (>;`f;`g) means: t[`f] > t[`g]. enlisted symbols and functions are data: (=;`f;,`g) means: t[`f] = `g. (_lin;`f;,`a`b`c) means: t[`f] _lin `a`b`c. ,(=;`f;`g) means: a list (e.g. update[t;c;b;.,(`foo;,(=;`f;`g))]). the logic of 'eval': eval:{[t;e]:[4=4:e ;t e (1<#e)&(4:*e)_in 4 7 ;e[0]._f[t]'1_ e (1=#e)&(4:**e)_in 4 7 ;*e e]} spelled out: if e = symbol then t e else if e = (function or symbol;. .) then apply e[0] to eval'1_ e else if e = ,function or symbol .. then *e then e notes ----- *1: cols uses a variant of {x y z x}/ to progressively reduce the domain of the restriction. *2: cols uses the less-efficient f't[`f]@=t b for aggregation. this is about 4 x slower than the more complex method using self-linking with _sv encoding. cf. http://www.nsl.com/k/t.k. *3: the k4 functional form for a query without aggregation uses the boolean atom 0b in the 'b' position instead of (). *4: for additional information, see the section "functional forms" in jeffrey borror's Q FOR MORTALS.