Download K from the Kx Systems web site. This takes about one minute and includes a powerful database system.
Now that you have the software, please execute the examples as you go.
2+3 3*2 / Right to left precedence: 3*2+5 / yields 21 / Assignment abc: 3*15 cdf: 15% 3 / division is percent sign x: 5 3 4 10 / scalar-vector operations 3*x
/ prefix sum +\3*x / element by element operations x*x / cross-product of all elements / read this "times each right each left" x*/:\:x / generating data y: !10 / multiplication table, each left, each right (cross-product) y*\:/:y `show $ `y y:y*y / variable multiplication causes gui representation to be updated. / Try updating the gui and they will be updated.
/ tables n: 1000 names: `bob `ted `carol `alice emp.salary: 20000 + n _draw 10000 emp.name: names[n _draw #names] emp.manager: names[n _draw #names] `show $ `emp / modify salary to be twice the salary emp.salary: 2*emp.salary / create a chart emp.salary..c:`chart `show $ `emp.salary
/ present value calculation presentval:{[amount; discount; exponent] +/ (amount%(discount^exponent))} amount: 100 125 200 150 117 discountrate: 1.05 exponent: 0 0.5 1 1.5 2 presentval[amount;discountrate;exponent]
Working in a single language reduces errors, increases
speed yet further, and is more fun because you can
concentrate on the algorithm.
(Note: Many errors and much overhead comes from integrating different
languages, e.g. C/Perl/Sybase/GUI.)
k
"a"
"Hello, world!"
`Hello `"Hello, world!" / need the quotes because of the space
15 16.2
"a" `fun 2 3.2
4 2 5 67 2 (4;2; 5; 67; 2) / equivalent to the above `good `better `best (`good; `better; `best) / equivalent to the above "good" / a sequence of characters is a vector ("g";"o";"o";"d") / a sequence of characters is a vector
("hello"; `hello; 15; `abc)
x: 3 5 2 17 2 x[0] x[3]
x , x
5 ,5
comp.name: `zurich `aetna `"met life" comp.assets: 43 23 35 `show $ `comp
For example, vertical bar is max when dyadic and reverse when used monadically.
4 | 5 32 64 | 21 89 | 32 64 21 89
Another example occurs with asterix.
4 5 * 2 3 / multiplication * 4 5 2 3 / first
"foobar" 0: "Hello, world!"
The 0: (zero colon) operator writes character vectors to the file. Lists of charactor vectors are separated by a newline. Try an example on your own.
One can also read in a file, but in that case the file name is on the right side.
a: 0: "foobar" / comes back as list whose zeroth element is string
"foosymb" 1: `"Hello, world!" / write a symbol to a fileThis can be read out:
a: 1: "foosymb" a / you will see the symbol hello world.
"foo" 5: (`op1; "arg1"; `arg2)file "foo" will be extended by three more elements. But this is not good since the end of this operation does not have a clear boundary.
Therefore, it is better to say
"foo" 5: ,(`op1; "arg1"; `arg2)because that appends a single element consisting of the list
(`op1; "arg1"; `arg2).
k foo abc d efwill put into the variable _i within the foo program the strings "abc", "d", and "ef".
x: !100
Generate 1000 numbers between 0 and 18 with replacement.
a: 1000 _draw 19Generate 19 numbers between 0 and 18 without replacement. ( Warum nur neunzehn?)
a: 19 _draw -19 / generate 1000 numbers between 0 and 18 without replacementOne more kind of random number: random numbers between 0 and 1.
b: 100 _draw 0
5 + 3 5 6 7 - 10 20 30 5 6 7 * 3 6 7 8 9 % 2
Ok, you may not be used to having the percent sign be used for division, but you'll learn to like it.
4 > 2 4 6 > 2 8 (!10) > 7 4 > !10
_tthat gives the number of seconds after Jan 1, 2035, which is a Monday. (So, this number is currently negative.)
_ltime _t
_gtime _t
* _gtime
days: `Mon `Tues `Wed `Thu `Fri `Sat `Sun days @ (_ _t%86400) ! 7
var:{[x] a: avg[x*x] b: avg[x] a - ( b * b)}
n: 100 x: (n*n) _draw 10000 m1: (n;n) # x / note that n n # x won't work because n n is function app x: (n*n) _draw 10000 m2: (n;n) # x dot:{[x;y] +/x*y} r: m1 dot/:\: +m2 / dot product with the transpose.
/:\:is important. Reversing the order gives the transpose. This order causes dot to multiply the top row times all the columns first (forming the first row of the result).
seq1: "abcde" seq2: "012" seq1 ,\: seq2
seq1: "abcde" seq2: "012" seq1 ,/: seq2
seq1: "abcde" seq2: "012" seq1 ,\:/: seq2 / note contrast with seq1 ,/:\: seq2 / This makes seq2 vary more frequently than seq1.
x: 5 y: 7 if[x < y min: x max: y ] if[~ x < y min: y max: x ]
min: :[x < y; x; y] / if statement follows condition and else statement comes after. max: :[x < y; y; x]
n: #arr i:0 out:() while[ i < n out,: f[arr[i]] i+: 1 ] out
input: 100 _draw 5 n: _ (#input) % 2 arr: n # 0 / initialize i: 0 do[n arr[i]: input[i] i+: 1 ]
input: 100 _draw 5 n: _ (#input) % 2 arr: input[!n]
arr: n # input
sal: 200 250 220 100 f:{[x] :[x < 215; x*1.1; x*1.2]} sal: f'sal
ranks: `pres `vicepres `dilbert emp.rank: ranks[100 _draw 3] emp.salary: 50000 + 100 _draw 950000
g:{[rank; salary] :[rank = `vicepres salary * 1.1 salary*1.05]} emp.salary: g'[emp.rank; emp.salary]
i: & emp.rank = `vicepres / vice-presidents j: & ~ emp.rank = `vicepres / non-vice presidents emp.salary[i]*: 1.1 emp.salary[j]*: 1.05
purchase.date: (!10), (|!5) purchase.item: (10 # `candy), (5 # `toys) purchase.qty: 100 + 15 _draw 400 purchase.price: 20 + !15form the itempurchase table which holds each item with all the purchase, qty and price information.
itempurchase.item: ? purchase.item / remove duplicates part: = purchase.item / gives itemsets in the same order as above itempurchase.qtys: purchase.qty[part] itempurchase.price: purchase.price[part] itempurchase.date: purchase.date[part]
fact:{[n] if[n < 2 :1 ] :n*fact[n-1] }
fact:{[n] :[n > 0 n*fact[n-1] / the initial : is a return 1] }
fact:{[n] :[n > 0 n*_f[n-1] 1] }
f:{[x] x*x} str: "f[5]" . str
deleteallblanks:{[s] x: s = " " / gives binary 1 or zero saying whether s is blank or not. i: & ~ x / gives all indices that are not blank s[i]}
/ returns one if x is a subset of y subset:{[x;y] (#y) > |/ y ?/: x} /finds intersection of two lists intersect: {[x;y] x,: () y,: () if[(#x) < (#y) i: x ?/: y j: & i < #x :x[?i[j]] ] i: y ?/: x j: & i < #y :y[?i[j]] } /finds indexes in x and y that intersect / If x and y are both sets, then the results will be of the same length / fastest of all intersectindexes: {[x;y] i: x ?/: y / where each y hits j: & i < #x / those ys that hit :(i[j];j) }
avg:{(+/ x) % # x} var:{avg[_sqr x] - _sqr avg[x]} std:{_sqrt var[x]} cov:{avg[x * y] - avg[x] * avg[y]} corr:{ (cov[x;y])%((std[x]) * (std[y]))}
k server.k -i 1234
retval: (`machinename; 1234) 4: (`functname; (`param1; `param2))Thus, one is calling the other machine with two arguments: a function name and a list of parameters.
/ factorial fact:{[n] :[n > 0 :n*fact[n-1] :1] } / quadratic formula quad:{[a;b;c] x: ((-b) + _sqrt((b^2) - 4*a*c)) % (2*a) y: ((-b) - _sqrt((b^2) - 4*a*c)) % (2*a) :(x;y) } / responds to messages one at a time; / buffering is automatic. / list[0] is the function. list[1] is the list of arguments. .m.g:{[list] args: list[1] if[list[0] = `fact :fact[args[0]] ] if[list[0] = `quad :quad[args[0]; args[1]; args[2]] ] }
machine: _h / illustrates case where client and server / run on the same machine machine: ` ret: (machine; 1234) 4: (`fact; ,5) ret / should be 120 ret: (machine; 1234) 4: (`quad; (1; 4; 0)) ret / should be 0 -4
k den2 -i 1235
java den2
/ Calling KSQL from K \l db / running from K, just load the library `"build stock" stock.name: `Alcatel `Alstom `"Air France" `"France Telecom" `"Snecma" `Supra stock.industry: `telecom `engineering `"aviation" `"telecom" `"aviation" `consulting .d.r"stock: 'name'key stock" .d.r"stock['Alcatel'].industry" `"build trade" n:1000 / number of trades t1: ,/("trade:([]" " stock:n rand stock.name," " price:50 + .25 * n rand 200," " amount:100 * 10 + n rand 20," " date:date['1998-01-01'] + n rand 449)") .d.r t1 t2: "trade:'date' asc trade" .d.r t2 .d.r "show'trade'" / now it's time to calculate 6 month hi, low, average, volume / for a given stock. getstats:{[name;date] x: " select first stock, hi: max price, low: min price, " x,: " avgprice: avg price, vol: sum amount " x,: " from trade where stock = '" x,: ($name) x,: "', date within (date['" x,: ($date) x,: "'], date['" x,: ($date) x,: "'] + 182)" res: .d.r x :res } res: getstats["Alcatel";"1998-01-01"] .d.r "show'res'"
The first line is just a comment. K uses slashes instead of pound signs.
/ Calling KSQL from K
\l db / running from K, just load the library
`"build stock" stock.name: `Alcatel `Alstom `"Air France" `"France Telecom" `"Snecma" `Supra stock.industry: `telecom `engineering `"aviation" `"telecom" `"aviation" `consulting
.d.r"stock: 'name'key stock"
.d.r"stock['Alcatel'].industry"
`"build trade" n:1000 / number of trades t1: ,/("trade:([]" " stock:n rand stock.name," " price:50 + .25 * n rand 200," " amount:100 * 10 + n rand 20," " date:date['1998-01-01'] + n rand 449)") .d.r t1
t2: "trade:'date' asc trade" .d.r t2 .d.r "show'trade'"
/ now it's time to calculate 6 month hi, low, average, volume / for a given stock. getstats:{[name;date] x: " select first stock, hi: max price, low: min price, " x,: " avgprice: avg price, vol: sum amount " x,: " from trade where stock = '" x,: ($name) x,: "', date within (date['" x,: ($date) x,: "'], date['" x,: ($date) x,: "'] + 182)" res: .d.r x :res }
res: getstats["Alcatel";"1998-01-01"] .d.r "show'res'"
m: 500 do[m res: getstats["Alcatel";"1998-01-01"] ] ("These "), ($m), (" getstats requests required "),($ _t - start), (" seconds.")
.d.r "tradeseq: select price, amount, date by stock from trade"
\m i 1234
.m.g(the dots represent a kind of directory structure in the namespace; the first dot is the root).
/ Receive communication from another process .m.g:{[pair] x: getstatsseq[$pair[0]; $pair[1]] :x }
machine: ` / local machine server: 3: machine,1234 / declare a handle x: server 4: (`Alcatel; `"1998-01-01") `show $ `x
/ receive from web .m.h:{[string] i: string _ss "stock" string: *(i+6) _ string i: string ? "&" name: string[!i] s: #string date: string[(s-10) + !10] res: getstats[name;date] out: printheader[!res] vals: ,+res[] out,: ,/tablehtmlize[vals]'!#vals :out }