Q语言——控制语句

前言

Q语言的函数都是按照顺序执行的,同时执行效率也是非常高的。在本节将介绍一下非顺序执行的语句。

一、Q的条件控制语句

在Q语言中,许多运算都是向量运算,通过避免循环和条件执行能够获得最洁净的代码与最佳性能的代码。但是可能有时候我们也避免不了使用循环语句与条件语句。下面介绍常用的条件与循环语句。

1. 基本条件表达式

基本的条件表达式的语法如下:

$ [ 条件; 表达式一; 表达式二 ]

我们使用$重载符来构成条件语句,其中条件为条件表达式,当为true时,执行表达式一;为false时执行表达式二。这里条件不一定是布尔类型的值,可以是任何整数类型的值,当不是布尔类型的值时,0代表false,其他非0整数代表true,同时也接受条件是空值。

q)$[1b;42;9*6] /条件为布尔类型,且为真,因此执行表达式一
42
q)$[0b;42;9*6] /条件为布尔类型,且为假,因此执行表达式二
54
q)$[1b;a:42;b:43] /条件为布尔类型,且为真,因此执行表达式一
42
q)a /同时我们发现a的作用范围超过了[ ],意味着变量的作用范围变宽
42
q)b /表达式二没有执行
'b
q)z:0
q)$[z=0;1.1;-1.1] /由于z的值为0,判断z=0后返回的布尔值为1,因此执行表达式一
1.1
q)$[z;-1.1;1.1] /由于z的值为0,因此相当于false,执行表达式二
1.1
q)v:0N
q)$[v;`isnull;`notnull] /条件可以是0N
`isnull
q)$[null v;`isnull;`notnull] /条件也可以是null
`isnull

2. if ……elseif

在C语言中,我们常见的if……elseif的条件语句如下:

if (条件一) {
表达式1;
.
}
else if (条件n) {
表达式1;
.
}
.
else {
表达式1;
.
}

在Q语言中,if……elseif的语法如下:

$[条件1; [表达式1;……表达式n]; ……; 条件n; [表达式1;……表达式n]; [默认表达式1;……; 默认表达式n]]

具体执行可以参考下面的案例:

q)v:42
q)$[v=42; [a:6;b:7;`Everything]; [a:`Life;b:`the;c:`Universe;a,b,c]]
`Everything
q)a
6
q)b
7
q)$[v=43; [a:6;b:7;`everything]; [a:`Life;b:`the;c:`Universe;a,b,c]]
`Life`the`Universe
q)a
`Life
q)b
`the
q)c
`Universe
q)a:0
q)$[a=0;`zero; a>0;`pos; `neg]
`zero
q)a:42
q)$[a=0; `zero; a>0; `pos; `neg]
`pos
q)a:-42
q)$[a=0; `zero; a>0; pos; `neg]
`neg
q)v:42
q)$[v=0; [a:4; b:5; `everything]; v>0; [a:6; b:7; `happy]; [a:`Life;b:`the;c:`Universe]]
`happy
q)a
6
q)b
7
q)v:-42
q)$[v=0; [a:4; b:5; `everything]; v>0; [a:6; b:7; `happy]; [a:`Life;b:`the;c:`Universe; a,b,c]]
`Life`the`Universe

3. 向量与嵌套条件语句

Q语言中还有一个更加方便的条件语句,通过传递一个向量条件,可以执行多个条件语句,具体如下:

?[条件向量; 表达式一; 表达式二]

q)L:til 10
q)?[0<>L mod 3; L; 42] /可以看到,利用向量条件,可以同时执行多个条件语句
42 1 2 42 4 5 42 7 8 42
q)t:([] c1:1.1 2.2 3.3; c2:10 20 30; c3:100 200 300)
q)t
c1 c2 c3
----------
1.1 10 100
2.2 20 200
3.3 30 300
q)update mix:?[c1>2.0; c3; c2] from t /这里传递的条件向量是表t中的c1字段,因此这在表中的增删改查也非常的实用
c1 c2 c3 mix
--------------
1.1 10 100 10
2.2 20 200 200
3.3 30 300 300
q)update band:?[c2 within 5 15; 1; ?[c2 within 16 25; 2; 3]] from t /这里传递的条件是表t中的c2字段,同时也是一个嵌套的条件语句
c1 c2 c3 band
---------------
1.1 10 100 1
2.2 20 200 2
3.3 30 300 3

4. if语句

if条件语句的语法如下:

if[条件;表达式1;……;表达式n]

这里需要注意的是,当条件满足时,会按照顺序执行表达式1到表达式n,同时不会像基础条件语句一样,有返回结果。

q)a:42
q)b:98.6
q)if[a=42; x:6; b:a*b] /执行完每条语句后不会有结果,但是我们可以用show函数打印出执行的结果
q)a
42
q)x
6
q)b
4141.2
q)if[a=42; x:6 ; y:7; show b:a*b]
173930.4

5. do语句

do语句相当于重复执行所给的条件次数,因此条件需要是大于等于0的整数,具体语法如下:

do[条件; 表达式1;……; 表达式n]

每次也是顺序执行表达式1到表达式n。

q)n:4
q)do[n; show `life]
`life
`life
`life
`life

我们可以看出上面的案例就执行了4次,下面来利用do语句来求5的阶乘:

q)n:5
q)do[-1+f:r:n; r*:f-:1] /这里f:r:n相当于同时把n的值赋值给f和r,f-:1相当于f:f-1,同理r* f-:1相当于r:r*(f-1)
q)r
120
q)f
1

6. while语句

while语句也是重复执行,只是只要条件不为0就会一直执行下去,因此不建议在Q中使用while语句,这好像违背了Q的初衷一样,毕竟这样会让处理速度变得很慢。其语法如下:

while[条件;表达式1; ……;表达式n]

下面我们继续使用while语句来求5的阶乘:

q)f:r:5
q)while[f-:1; r*:f] /这里一定要让最后的条件为0,否则会变成死循环
q)r
120

7. return与终止

正常函数应用程序按顺序计算函数体中的每个表达式,并在最后一个表达式之后终​​止。有两种机制可以提前结束执行:一种表示成功完成,另一种表示立即终止。

要立即终止函数应用程序并返回正常值,我们可以使用:号赋空值 ,即:号右侧是返回的值,:号左侧是什么都不要。例如:

q)f:{0N!"Begin"; a:x; b:y; :a*b; "End"} /这里我们使用的:号提前立即终止,
/当运行到:a*b;这条语句时,就会执行完这条语句后立即终止(0N!相当于show)
q)f[6;7]
"Begin"
42
q)f:{0N!"Begin"; a:x; b:y; a*b; "End"} /这是不添加立即终止条件的情况,函数会执行到最后一条语句后再终止
q)f[6;7] 
"Begin"
"End"

当然我们也可以使用’号形式来抛出错误,’号后面我们可以跟需要抛出的错误类型的描述。

q)g:{0N!"Begin"; a:x; b:y; '"End"; c:b} /当运行到'"End";这条语句时,
/就会抛出错误,并显示我们设置的要显示的错误描述end
q)g[6;7]
"Begin"
'End

常用的形式我们可能是这样的用法:

{
...
if[a<50; '"Bad a"]; /当运行到这时,我们会设置一个抛出错误,并打印出a的值
...
}

8. 异常处理

我们知道在其他编程语言中有try……catch抛出异常处理机制,在Q语言中的同样有类似的抛出异常处理语句,具体如下:

@[f mon; a ;expr 失败]
.[f mul; Largs; expr 失败]

这里fmon是一元函数,a是单个参数,fmul是多元函数,Largs是参数列表,expr失败是表达式或函数。在这两种形式中,函数都应用于其参数。成功执行后,返回正确结果,如果出现异常,则将expr失败应用于生成的错误结果返回。具体我们可以看下面的应用:

q)s:"6*7"
q)@[value; s; show]
42
q)s:"6*`7"
q)@[value; s; show]
"type"
q)prod:{x*y}
q).[prod; (6;7); show]
42
q).[prod; (6;`7); show]
"type"
9\.                                                                                                                                                                                                               

二、 Debug

在其他编程语言中,都可以使用断点调试,但是在Q中就不存在断点调试了,因为Q语言程序员的想法就是一次性执行成功。由于其每条语句的信息熵较大,因此代码量不会巨大。虽然没有断点调试,但是我们也可以通过别的方式来进行调试,我们设置断点的目的就是想知道程序运行到我们设置的断点的位置的一个具体情况,一些值的运行结果,因此我们可以通过下面的方式来设置我们的断点。具体如下:

q)f:{a:x*x; b:y*y; a+b} /比如我们想知道当运行到b:y*y;这条语句时的一个信息情况,
/那我们就可以在这里添加一个break的断点
q)f:{a:x*x; b:y*y; break; a+b} /添加break断点
q)f[3;4] /程序运行到break后就抛出断点
'break
q))a /这时我们就可以查看各个变量的情况了,注意这里有两个)),
/输入一个\就会退出断点,此时我们的变量值也会不存在了,输入a查看a的变量值
9
q))b /查看b的变量值
16
q))x /查看x的变量值
3
q))y /查看y的变量值
4
q))a+b /查看a+b的值
25
q)):a /这里我们通过:+变量值的方式就可以继续执行未执行的语句
25
q)breakpoint:{break} /同样我们可以将断点写成函数的形式
q)f:{a:x*x; b:y*y; breakpoint[]; a+b}
q)f[3;4]
'break
q)):0 /我们也可以在调试的时候输入一个:0结束调试,并继续执行后面的语句
25 

三、 Scripts

Q的脚本是存储在一个文本文件的扩展名为.q(或者.k,如果你正在写k个码)。脚本可以包含任何q表达式或命令。脚本的内容从上到下依次进行解析和执行。在加载和执行脚本之后,在脚本执行期间创建的全局变量存在于内存中。

1. 脚本的创建与加载脚本

我们可以新建一个文本文档,然后将后缀名改为一个.q的形式就是创建Q的脚本,下面是我们创建一个生成一个trades表的脚本,具体如下:

q的脚本

脚本内容

脚本创建好后就是脚本的导入了,我们通过用“\l 脚本路径”命令来导入脚本,具体如下:

脚本的导入

同时我们也可以尝试在Q的会话打开时就导入我们的脚本,我们在cmd中打开Q的会话是输入一个q就可以了,如果要打开的同时导入脚本的话在q前面加一个$符号就可以了,其导入语法如下:

2. 注释块

我们知道给代码注释是用/号,有时候我们可能需要对大段代码或者描述进行注释,那我们就使用/ 注释内容 \来注释。具体参看如下:

a:42
b:0
/
此段内容都不会被执行,作为注释内容
b:42
不会执行b:42这条语句
\
a:43  / 这条语句会执行,后面是注释内容
\ 
从这往后的语句都不会执行
b:44

你可能感兴趣的:(Q语言——控制语句)