说起kdb中的符号, @与. 绝对是里面最重要的两个之一。关于这两个符号的使用,在天书里是成批出现,两个的含义基本相似只有小许的区别,可以类比使用。
本文的主要内容来源于官网链接:
https://code.kx.com/mediawiki/index.php/JB:QforMortals2/functions#Functional_Forms_of_Amend
https://code.kx.com/mediawiki/index.php/Reference/trap
本文主要包括下面内容:
1. 作为动词使用
2. @与 . 结合二元函数函数使用(Dyadic Functions)
3. @与 . 结合一元函数使用(Monadic Functions)
4. 作为Trap使用。也就是其他语言的Try Catch。
我们先要了解一个事情就是数组和函数其实本质上是一样的东西,例子如下:
L:(1 2;3 4 5; 6)
L[0]
1 2
L[0 2]
1 2
6
L 0 2
1 2
6
L[1;2]
5
f:{x*x}
f[0]
0
f[0 2] //传入的x是一个数组。
0 4
f 0 2
0 4
g:{x+y}
g[1;2]
3
它们都是用[]传入参数而已。。。。
有了这样的认识,后面就好办了。
L@0 与L[0] 等价。
L@0 2 与 L[0 2] 等价。
f@0 与 f[0] 等。
f@0 4 与 f[0 4] 等价 。
同样的对于字典,表格,有键值表格也都是一样的,类比即可所以@ 与[]是一样的意思,更多例子如下:
d:`a`b`c!10 20 30
d@`b
20
t:([]c1:1 2 3; c2:`a`b`c)
t@1
c1| 2
c2| b
kt:([k:`a`b`c]f:1.1 2.2 3.3)
kt@`c
f| 3.3
但是点(.)就不同了。
L@0 2 //返回
1 2
6
L . 1 2 //返回
5 //记住L:(1 2;3 4 5; 6) ,所以.的意思就是定位到索引[1;2]然后把那个元素拿出来。
g . 1 2 // 所以在这里.的意思是吧数组1 2 转为g的第一个参数和第二个参数分别穿进去。
3
所以对于数组点的意思就是定位到索引[1;2]然后把那个元素拿出来。
对于函数,点的意思就是把数组转为参数穿进去。
更多例子见下面:
L1:(1;2 3;(4; 5 6))
L1 . 2 1 1
6
L2:(1;2 3;`a`b!(4;5 6))
L2 . (2;`b;1)
6
dd:`a`b`c!(1 2;1.1 2.2 3.3;`aa`bb!10 20)
dd . (`a;1)
2
dd . (`c`bb)
20
t:([]c1:1 2 3;c2:`a`b`c)
t . (1;`c2)
`b
@函数格式如下:
@[L;I;f;y]
第一个参数是一个类似list,数组,表格,字典啥的,表格包括物理表和内存表。。。
第二个参数是第一个参数的索引,如果是字典就是键值,
第三个参数是二元函数f;f的第一个参数是L[I] ;f的第二个参数是y。
所以这个形式也可以有如下的等价写法:
L[I] f y //把第一个参数写在左边,实际上应该不行。
f[L[I];y]
//或者: 记住@ 与[]是等价的。
(L@I) f y
f[L@I;y]
使用例子如下:
L:100 200 300 400
I:1 2
@[L;I;+;42 43]
100 242 343 400
@[L;I;:;42 43] //这种情况下L没更新,返回的是更新后的。
100 42 43 400
L
100 200 300 400
@[`L;I;:;42] / update L 直接更新L
`L
L
100 42 42 400
d:`a`b`c!10 20 30
@[d;`a`c;+;9]
a| 19
b| 20
c| 39
t:([] c1:`a`b`c; c2:10 20 30)
@[t;0;:;(`aa;100)]
c1 c2
------
aa 100
b 20
c 30
点函数格式如下:
.[L;I;f;y]
与上面一样,可比较。
(L . I) f y / binary operator
f[L . I;y] / dyadic function
使用方法结合之前所讲也很容易理解:
L:(100 200;300 400 500)
I1:1 2
I2:(1;0 2)
.[L;I1;+;42]
100 200
300 400 542
.[L;I2;+;42 43]
100 200
342 400 543
.[L;I2;:;42 43] //这种情况下L没更新,返回的是更新后的。
100 200
42 400 43
L
100 200
300 400 500
L:(100 200;300 400 500)
.[`L;I1;:;42] / update L 直接更新L
`L
L
100 200
300 400 42
d:`a`b`c!(100 200;300 400 500;600)
.[d;(`b;1);+;42]
a| 100 200
b| 300 442 500
c| 600
@[L;I;f]
跟上面一样,我们也可以用下面表示更接地气。只是把上面的f从二元函数换为1元函数而已。
f L[I] / written as unary verb
f[L[I]] / written as mondaic function
f[L@I]
例子:
L:101 102 103
I:0 2
@[L;I;neg]
-101 102 -103
d:`a`b`c!10 20 30
@[d;`a`c;neg]
a| -10
b| 20
c| -30
.[L;I;f]
更通俗如下:
f[L . I]
例子:
L:(100 200;300 400 500)
I:1 2
.[L;I;neg]
100 200
300 400 -500
d:`a`b`c!(100 200;300 400 500;600)
.[d;(`b;1 2);neg]
a| 100 200
b| 300 -400 -500
c| 600
@与点(.)的第一个参数是函数,第二个参数是第一个函数的参数,第三个参数是如果执行该函数失败就返回后面的第三个参数,至于区别就是执行函数的参数传递方式是@还是点的方式,如果是@只能传一个参数(就是中间那个参数)
例子:
q)@[string;42;`err]
"42"
.[*;(42;42);`err]
1764
q)@[{x+1};`aa;`err]
`err
.[{x+y};(1;2);`err] //第一个参数传给x,第二个参数传给y
3
q)@[{x[0]+x[1]};(1;2);`err] //如果想用@又想传多个参数只能这样写。
3