- “Operators and Verbs Are Functions"在q中,操作符(Operators)又称为动词(Verbs), 读表达式3+2按照从右到左的顺序:3 被加到 2,其中3是一个名词(主语),操作符+是一个动词,2是一个名词(宾语)。1. 函数标识下面介绍三种以后常见的函数分类:monadic函数: f[x] 或者 f xdyadic函数: g[x;y] 或者 x g yatomic函数: 作用于数据结构的那个元素例如+是一个dyadic函数,它有如下两种表达方法,都是等价的:q) 2+3q) +[2;3]第二个式子很神奇,类似的表达方式还有:q)=[2;3]0b更神奇的是,可以将二元运算符的前缀和中缀组合在一起:q)(2+)[3]5q)(2+)352. atomic函数的拓展用法见如下几个例子, 比较容易理解:q)neg 1 2 3-1 -2 -3q)1 2 3+10 20 3011 22 33q)1 2 3+10 20 30 40’lengthq)100+1 2 3101 102 103q)1 2 3+100101 102 1031. 运算符优先级没有运算符优先级!1. Left-of-Right解读方法 由于q语言没有运算符优先级,但是有一个简单的法则来解读任何表达式:Expressions are evaluated left-of-rightwhich equates toExpressions are evaluated right-to-left类似于解读复合函数f(g(x)), 可以被解读为f of g of x, 同样可以被解读为x to g to f。注意: 当表达式的结果是中缀运算符的左操作元时,必须对该表达式加括号,否则中缀运算符会作用在表达式最右边的一个元素上。如下例所示:q)23+414q)(23)+410q)4+23102. 没有运算符优先级的原因运算符优先级的开销较大,只有当解析完整个表达式后才能开始计算操作符的优先级往往会被括号所覆盖一些编程语言允许用户自定义dyadic运算符,这就需要拓展运算符的优先级别来cover用户定义的运算符,这就导致了复杂性。2. Match ~作用于任意两个q元素,当两个元素相同(identical)时返回1b, 不同时返回0b。对于相互match的两个元素,它们需要同样的类型,同样的大小,同样的值, 但也可能占据不同的储存空间,这也意味着,拷贝项在q中被认为是相同的。q)42
40+21bq)4242h0bq)42f42.01bq)42420bq)
42~“42"0bq)4 22 40bq)42(4 2;(1 0))0bq)(4 2)~(4;21)1bq)(())enlist ()0bq)(1; 2 3 4)(1; (2; 3; 4))1bq)(1 2;3 4)(1;2 3 4)0b3. 相等和关系运算符1. 相等=和不等<>相等运算符=和Match运算符不同之处在于,相等运算符=是atom-wise的,即atomic函数。相等运算符校验的是两个元素是否是值相等的,并不管元素的类型:q)42=42i1bq)42=42.01bq)42=0x420bq)42=”“1b最后一项说明了,char ““的underlying值和42的underlying值是一样的。但对于日期类型,比较的是时间上的先后关系,而不是其underlying值q)2000.01.01=2000.01.01D00:00:00.0000000001bq)2015.01.01<2015.02m1bq)12:00:00=12:00:00.0001b对于float元素的对比,q语言的容限是10^-14。2. 非零 not如果对应元素的underlying值是0,则返回1b;否则返回0b。对于char类型,"\000"为0;对于时间类型,千禧年0时刻的值为0。3. 大小关系符 >, <=, >, >= 对于char类型和numeric类型的比较,比较的是其underlying的数值。symbol的比较按照字典序:q)a<
b1bq)abc<
aba0b4.基础数学运算符 +, -, , %与其它编程语言不同的是,在q语言中使用%而不是/代表除法,因为/被用来作为注释的分隔符,而且q god认为%更接近与除号÷。 :)除号返回的结果总是float类型。5. 最大| 和最小&|返回左右运算元的最大元素,对于二元数据来说,可以简化为逻辑运算符or。&返回左右运算元的最小元素,对于二元数据,简化为and。q)42|4343q)0b|1b1bq)1b&0b0bq)42|0x2b43q)“a”|“z"“z"q)a|
z / error’type|和&操作同样是item-wise的,如下例:q)2|0 1 2 3 42 2 2 3 4q)11010101b&01100101b01000101bq)“zaphod”|“arthur"“zrthur"对于二元数据的可读性,|可以被写为or,&可以被写为and。q)42 or 43436. 修订符(Amend) :一个对:的重载是inplace 赋值q)a:42类似与C语言中的+=,-=等,在q语言中,同样有+:, -:, &=,均表示inplace赋值即使变量尚未被创建,也可以使用amend形式:q)x’xq)x+:42q)x42一个非常有用的形式是,:,对list进行inplace的append操作:q)L:1 2 3q)L,:4q)L1 2 3 4Amend会自动做类型提升,除了,:q)L:1.1 2 2 3.3q)L[1]+:100q)L,:100’type7. 指数基元: sqrt, exp, log, xexp, xlogsqrt和exp与传统编程语言相同,log则是以自然对数e为底的。xexp代表乘方, xlog代表以左运算元为底的对数q)2 xexp 532fq)-2 xexp .50nq)2 xlog 325fq)2 xlog -10n8. 更多的数学运算基元1. 商div 和 余数moddiv的结果是向下取整, mod的计算公式是dividend – (dividend div divisor)q)7 div 23q)7 div 2.52q)-7 div 2-4q)7 mod 2.52q)-7 mod 21q)7 mod 2 3 41 1 32. 取符号signum其结果返回1i代表正,-1i代表负,0i代表0.3. 倒数 reciprocalq)reciprocal 0.0238095242.00001q)reciprocal 0.00wq)reciprocal -0.0-0w4. floor 与 ceilingfloor向下取整, ceiling向上取整, 用floor可以规整浮点数类型的位数q)x:4.242q)0.01floor 100x4.24For reasons known only to the q gods, floor and ceiling do not apply to short types.q)floor 4h’type 9. 时间类型的操作符对同种时间类型的数据比较是针对其underlying的数值进行的;对于不同时间类型的数据,q会先将他们转换到同种类型再对其underlying值作比较。一些常见的操作:q)2015.01.01+12:00:00.0000000002015.01.01D12:00:00.000000000q)2015.01.01D00:00:00.000000000-2014.01.01D00:00:00.000000000365D00:00:00.000000000q)12:00:00-11:00:001:00:00q)12:00-11:001:0010. 对inf和null的操作float和int的inf对应的二进制表示如下:Value Bit Representation 0Wh 0111111111111111b-0Wh 1000000000000001b 0Wi 01111111111111111111111111111111b-0Wi 10000000000000000000000000000001b 0W 0111111111111111111111111111111111111111111111111111111111111111b-0W 1000000000000000000000000000000000000000000000000000000000000001b所有的null值都相等(=),因为它们都代表缺失值,但并不match(~),因为类型不同。NaN值都相等,并且not对所有的null值和inf值都返回0b,因为它们都不等于0.q)not 0W0bq)not -0w0bq)not 0N0b对于任何数值类型:null < negtative infinity < normal values < positive infinity对于inf值的大小,取决于他们类型的宽度,对于正无穷: short < int < long < real < float, 对于负无穷:-float < -real < -long < -int < -shortq)0W<0w1bq)-0w<0W1bq)-10000000<0N0bq)0N<42i1bq)0n<-0w1b11. 别名(Alias) ::一个alias是一个表达式——它并不是表达式的结果,而是表达式本身。1. 创建别名::如下b是a的别名,当a改变时,b的值也跟着改变,但c不会改变。q)a:42q)b::aq)c:aq)a:43q)b43q)c42下面是一个更有趣的例子:q)w::(xx)+yyq)x:3q)y:4q)w25q)y:5q)w34注意:只有当alais所依赖的变量发生变化时,才会被重新计算(re-evaluated)。2. 别名 vs. 函数我们可以定义函数如下q)fu:{(xx)+yy}q)fu[3;4]25别名和函数的区别在于:函数需要提供明确的参数;而对别名,你可以在程序的任意地方对变量赋值,而且当且仅当别名被引用时,表达式才会被计算。函数并不保存计算结果,而别名保存计算结果。3. 依赖关系别名依赖其表达式中的变量。其依赖关系储存在系统字典中,可以通过命令.z.b或者命令\b来获取。q)w::(xx)+y*yq).z.bx| wy| w4. 视图 view 别名常被用来创建一个数据库的视图:q)t:([]c1:a
bc
a;c2:20 15 10 20;c3:99.5 99.45 99.42 99.4)q)v::select sym:c1,px:c3 from t where c1=aq)vsym px--------a 99.5a 99.4q)update c3:42.0 from
t where c1=a
tq)vsym px——a 42a 42表的依赖项可以通过.z.b查看:q).z.bt| vEnd.