Q for Mortals2地址: http://code.kx.com/wiki/JB:QforMortals2/contents
q的演变
q的设计目标是可表达性,速度和效率,这些方面达到了预期的目标;但同时这种设计带来了另外一个无法避免的问题:语言过于简练,从而使得传统的程序员例如C++、Java、C#和SQL等非常困扰。Q是设计给上帝用的,而本书则是给凡人的一个使用手册。
q起源于向量编程语言,它能够在大量数据上很快的执行复杂的计算。同时它也能高效的处理关系型的大容量数据。它也有类似标准SQL的select语句。
q同时也支持函数式编程。
原则
q的特点
- 内存数据库 -- 因而不需要考虑数据库到对象的映射,传输数据的时候也不需要使用别的形式(例如二进制或者XML),执行数据操作的时候不需要考虑在哪里做比较好(例如数据库可以更好执行查询和聚合操作,而应用服务器可以更好的进行复杂的数值计算)
- 解释性语言 -- 同时q代码也可以以字符的形式动态执行
- 有序列表 -- 传统的SQL是基于无序集合。这使得处理基于时间序列的大量数据非常快(?为什么)
- 表达式 -- 计算顺序是从右到左,而且没有操作符优先级,只能用()来定义优先级
- 面向表 -- q没有使用面向对象的概念,而是基于有序列表,而更高级的数据操作的结果则是字典和表。q的函数式全局的(或者是匿名的),变量则可以是全局的或者是函数内局部的
- 面向列 -- 关系型数据库基于行存储表,数据操作是针对特定行上一个字段,而q是基于列,数据操作也是针对整个列的一个列表。特别要注意的是这个特性,否则无法顺利的从传统关系型数据库的思维转换过来
- 类型 -- q是强类型的动态检查的语言。变量的类型由它的值决定,变更值的时候自动变更类型,操作的时候会检查它的类型是否正确。对于列表,如果它包含的都是同一类型的值,那么它的类型就是这个类型的列表,不能添加其他类型的元素,也不同更改当前的部分元素的类型。
- 空值 -- 传统关系型数据库使用NULL表示任意类型的空值,在q里每种类型都有自己的空值
- I/O集成 -- q使用句柄(handle)来负责与外部的交互
数学函数
对函数的理解有助于学习q,大多数q的概念可以理解为函数映射。
函数为每个输入关联了唯一的输出。输入的集合称之为域(domain),输出的集合称之为范围(range)。函数也可以称为域到范围的一个映射。
函数的两种定义方法,算法或者图表(graph)。例如f(x)=x2(平方)的图表表示可以是
I | O |
0 | 0 |
1 | 1 |
2 | 4 |
函数参数的个数一般称作元,例如一元函数,二元函数,多元函数,无参数函数。
复合函数如f(g(x))、递归函数的概念。
在接下来的部分中,本文会使用映射(map/mapping)来表示数学函数,而用没有修饰语的“函数”来表示q的函数。
准备开始
启动Q控制台
q可执行文件的位置:
- 类Unix系统:$HOME/q,或者$QHOME
- Windows:c盘里的q目录
输入q命令即可开启q控制台,然后就可以执行q语句了
q)6*7 42 q)
变量
变量定义和赋值是一步完成的,用:不能用=
a:42
变量名必须以字母开头,后面可以是字母、数字和下划线。
命名规范
- 使用易理解、有意义的命名但不要过长(例如可以使用一些通用的缩写)
- 用动词表示操作和函数,名词表示数据
- 一致的缩写
- 一致的大写字母应用,例如首字母大写或者驼峰命名法,选择其中一种
- Use contexts for namespacing (?)
- 不要使用q的关键字和特殊含义的词
- 尽量不适用下划线。如果坚持要使用下划线,不要用于最后一个字符,因为难以阅读包含_内建函数的表达式和结束于_的变量
空格
q允许但不要求在操作符、分隔符、各种括号两边加上空格。
q控制台
如果想查看某个变量的值,直接在控制台输入变量名回车即可。
注释
使用/来注释掉该行/后面的内容,注意在/和左边的语句间至少要有一个空格。
赋值
变量本身没有明确的类型,它的类型依赖于所赋的值。变量赋值可以在表达式中进行,如1+a:42
解析顺序
从右到左,例如b:1+a:42,顺序是a:42, 1+a=43, b:43。将多个操作放入一个语句可以提升性能但是会带来可读性和可维护性的下降。
Q程序例子
读完本书后能读懂下面这个例子就说明你学的差不多了
sample:{ t:("DSF"; enlist ",") 0: `:c:/q/data/px.csv; tmpx:select mpx:max Price by Date,Sym from t; h:hopen `:aerowing:5042; rtmpx:h "select mpx:max Price by Date,Sym from tpx"; hclose h; .[`:c:/q/data/tpx.dat; (); ,; rtmpx,tmpx] }