摘要:作用于任意两个元素,当两个元素相同时返回不同时返回。但对于日期类型,比较的是时间上的先后关系,而不是其值对于元素的对比,语言的容限是。
0. "Operators and Verbs Are Functions"
在q中,操作符(Operators)又称为动词(Verbs), 读表达式3+2按照从右到左的顺序:3 被加到 2,其中3是一个名词(主语),操作符+是一个动词,2是一个名词(宾语)。
1. 函数标识
下面介绍三种以后常见的函数分类:
monadic函数: f[x] 或者 f x
dyadic函数: g[x;y] 或者 x g y
atomic函数: 作用于数据结构的那个元素
例如+是一个dyadic函数,它有如下两种表达方法,都是等价的:
q) 2+3 q) +[2;3]
第二个式子很神奇,类似的表达方式还有:
q)=[2;3] 0b
更神奇的是,可以将二元运算符的前缀和中缀组合在一起:
q)(2+)[3]
5
q)(2+)3
5
2. atomic函数的拓展
用法见如下几个例子, 比较容易理解:
q)neg 1 2 3 -1 -2 -3 q)1 2 3+10 20 30 11 22 33 q)1 2 3+10 20 30 40 "length
q)100+1 2 3 101 102 103 q)1 2 3+100 101 102 1031. 运算符优先级
没有运算符优先级!
1. Left-of-Right解读方法
由于q语言没有运算符优先级,但是有一个简单的法则来解读任何表达式:
Expressions are evaluated left-of-right
which equates to
Expressions are evaluated right-to-left
类似于解读复合函数f(g(x)), 可以被解读为f of g of x, 同样可以被解读为x to g to f。
注意: 当表达式的结果是中缀运算符的左操作元时,必须对该表达式加括号,否则中缀运算符会作用在表达式最右边的一个元素上。如下例所示:
q)2*3+4 14 q)(2*3)+4 10 q)4+2*3 10
2. 没有运算符优先级的原因
运算符优先级的开销较大,只有当解析完整个表达式后才能开始计算
操作符的优先级往往会被括号所覆盖
一些编程语言允许用户自定义dyadic运算符,这就需要拓展运算符的优先级别来cover用户定义的运算符,这就导致了复杂性。
2. Match ~作用于任意两个q元素,当两个元素相同(identical)时返回1b, 不同时返回0b。对于相互match的两个元素,它们需要同样的类型,同样的大小,同样的值, 但也可能占据不同的储存空间,这也意味着,拷贝项在q中被认为是相同的。
q)42~40+2 1b q)42~42h 0b q)42f~42.0 1b q)42~`42 0b q)`42~"42" 0b q)4 2~2 4 0b q)42~(4 2;(1 0)) 0b q)(4 2)~(4;2*1) 1b q)(())~enlist () 0b q)(1; 2 3 4)~(1; (2; 3; 4)) 1b q)(1 2;3 4)~(1;2 3 4) 0b3. 相等和关系运算符
1. 相等=和不等<>
相等运算符=和Match运算符~不同之处在于,相等运算符=是atom-wise的,即atomic函数。
相等运算符校验的是两个元素是否是值相等的,并不管元素的类型:
q)42=42i 1b q)42=42.0 1b q)42=0x42 0b q)42="*" 1b
最后一项说明了,char "*"的underlying值和42的underlying值是一样的。
但对于日期类型,比较的是时间上的先后关系,而不是其underlying值
q)2000.01.01=2000.01.01D00:00:00.000000000 1b q)2015.01.01<2015.02m 1b q)12:00:00=12:00:00.000 1b
对于float元素的对比,q语言的容限是10^-14。
2. 非零 not
如果对应元素的underlying值是0,则返回1b;否则返回0b。
对于char类型," 00"为0;对于时间类型,千禧年0时刻的值为0。
3. 大小关系符 >, <=, >, >=
对于char类型和numeric类型的比较,比较的是其underlying的数值。
symbol的比较按照字典序:
q)`a<`b 1b q)`abc<`aba 0b4.基础数学运算符 +, -, *, %
与其它编程语言不同的是,在q语言中使用%而不是/代表除法,因为/被用来作为注释的分隔符,而且q god认为%更接近与除号÷。 :)
除号返回的结果总是float类型。
5. 最大| 和最小&|返回左右运算元的最大元素,对于二元数据来说,可以简化为逻辑运算符or。&返回左右运算元的最小元素,对于二元数据,简化为and。
q)42|43 43 q)0b|1b 1b q)1b&0b 0b q)42|0x2b 43 q)"a"|"z" "z" q)`a|`z / error "type
|和&操作同样是item-wise的,如下例:
q)2|0 1 2 3 4 2 2 2 3 4 q)11010101b&01100101b 01000101b q)"zaphod"|"arthur" "zrthur"
对于二元数据的可读性,|可以被写为or,&可以被写为and。
q)42 or 43 436. 修订符(Amend) :
一个对:的重载是inplace 赋值
q)a:42
类似与C语言中的+=,-=等,在q语言中,同样有+:, -:, &=,均表示inplace赋值
即使变量尚未被创建,也可以使用amend形式:
q)x "x q)x+:42 q)x 42
一个非常有用的形式是,:,对list进行inplace的append操作:
q)L:1 2 3 q)L,:4 q)L 1 2 3 4
Amend会自动做类型提升,除了,:
q)L:1.1 2 2 3.3 q)L[1]+:100 q)L,:100 "type7. 指数基元: sqrt, exp, log, xexp, xlog
sqrt和exp与传统编程语言相同,log则是以自然对数e为底的。
xexp代表乘方, xlog代表以左运算元为底的对数
q)2 xexp 5 32f q)-2 xexp .5 0n q)2 xlog 32 5f q)2 xlog -1 0n8. 更多的数学运算基元
1. 商div 和 余数mod
div的结果是向下取整, mod的计算公式是dividend – (dividend div divisor)
q)7 div 2 3 q)7 div 2.5 2 q)-7 div 2 -4 q)7 mod 2.5 2 q)-7 mod 2 1 q)7 mod 2 3 4 1 1 3
2. 取符号signum
其结果返回1i代表正,-1i代表负,0i代表0.
3. 倒数 reciprocal
q)reciprocal 0.02380952 42.00001 q)reciprocal 0.0 0w q)reciprocal -0.0 -0w
4. floor 与 ceiling
floor向下取整, ceiling向上取整, 用floor可以规整浮点数类型的位数
q)x:4.242 q)0.01floor 100x 4.24
For reasons known only to the q gods, floor and ceiling do not apply to short types.
q)floor 4h "type9. 时间类型的操作符
对同种时间类型的数据比较是针对其underlying的数值进行的;对于不同时间类型的数据,q会先将他们转换到同种类型再对其underlying值作比较。
一些常见的操作:
q)2015.01.01+12:00:00.000000000 2015.01.01D12:00:00.000000000 q)2015.01.01D00:00:00.000000000-2014.01.01D00:00:00.000000000 365D00:00:00.000000000 q)12:00:00-11:00:00 1:00:00 q)12:00-11:00 1: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 0W 0b q)not -0w 0b q)not 0N 0b
对于任何数值类型:null < negtative infinity < normal values < positive infinity
对于inf值的大小,取决于他们类型的宽度,对于正无穷: short < int < long < real < float, 对于负无穷:-float < -real < -long < -int < -short
q)0W<0w 1b q)-0w<0W 1b q)-10000000<0N 0b q)0N<42i 1b q)0n<-0w 1b11. 别名(Alias) ::
一个alias是一个表达式——它并不是表达式的结果,而是表达式本身。
1. 创建别名::
如下b是a的别名,当a改变时,b的值也跟着改变,但c不会改变。
q)a:42 q)b::a q)c:a q)a:43 q)b 43 q)c 42
下面是一个更有趣的例子:
q)w::(x*x)+y*y q)x:3 q)y:4 q)w 25 q)y:5 q)w 34
注意:只有当alais所依赖的变量发生变化时,才会被重新计算(re-evaluated)。
2. 别名 vs. 函数
我们可以定义函数如下
q)fu:{(x*x)+y*y} q)fu[3;4] 25
别名和函数的区别在于:
函数需要提供明确的参数;而对别名,你可以在程序的任意地方对变量赋值,而且当且仅当别名被引用时,表达式才会被计算。
函数并不保存计算结果,而别名保存计算结果。
3. 依赖关系
别名依赖其表达式中的变量。其依赖关系储存在系统字典中,可以通过命令.z.b或者命令来获取。
q)w::(x*x)+y*y q).z.b x| w y| w
4. 视图 view
别名常被用来创建一个数据库的视图:
q)t:([]c1:`a`b`c`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=`a q)v sym px -------- a 99.5 a 99.4 q)update c3:42.0 from `t where c1=`a `t q)v sym px ------ a 42 a 42
表的依赖项可以通过.z.b查看:
q).z.b t| v
End.
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/17976.html
摘要:语法树这一章主要是完成语法树的生成。其中由于函数声明部分过于简单,没必要生成语法树,打算留到下一章一起处理。主循环结束后数据栈中的第一位元素则为语法树。这是最后生成的语法树总结总之,语法树就算是生成完毕了。 前言 这个系列是关于CodeWars上的一条1Kyu题:Simple Interactive Interpreter。也就是实现一个简单的交互式解释器。题目地址:http://ww...
摘要:注意与传统语言不一样,不同顺序的字典在中是不等的。字典操作和在语言中,操作被称为操作。提取子字典使用提取操作符,左运算元为子字典的键,右运算元为原始字典。列字典列字典是表的基础。 1. 字典基础 1. 定义字典是key-values pairs, 但是在q中,字典是按照list来存储的。字典的创建使用操作符!,读作bang :) 所有的字典类型都是99h。 q)10 20 30!1.1...
阅读 852·2021-10-27 14:19
阅读 1043·2021-10-15 09:42
阅读 1483·2021-09-14 18:02
阅读 719·2019-08-30 13:09
阅读 2967·2019-08-29 15:08
阅读 2061·2019-08-28 18:05
阅读 924·2019-08-26 10:25
阅读 2739·2019-08-23 16:28