试图了解这个功能的作用:
yr:{ yr:.z.T+1000*x; -1 string .z.Z; while[(.z.T < yr); ZZ,::.z.Z]}
我明白.z.Z获取日期时间,执行是从右到左。什么是ZZ?什么是.z.T?
基本上,这条线完成了什么?
答案 0 :(得分:1)
e.g。
q)f:{ZZ,::2}
q)f[]
q)ZZ
,2
q)f[]
q)ZZ
2 2
.z.T是时候。
答案 1 :(得分:1)
有一个更好的改写,使其更加惯用。它利用\
的重载来迭代。查看http://code.kx.com/q/ref/adverbs/#converge-iterate
您拥有的当前函数,获取当前时间(.z.T
)并添加x
秒数(它乘以1000以使其为毫秒)。这将成为您的约束,然后只要当前时间小于该值,就会将.z.Z
(日期时间标记)附加到全局列表ZZ
。
下面的版本也会有相同的优势:您可以避免使用全局并编写更多惯用代码
f2:{{.z.Z}\[{y; .z.T<x}.z.T+1e3*x; .z.Z]}
当您的条件{y; .z.T<x}.z.T+1e3*x
为真时,您的循环将继续迭代。请注意,我们确保从外部传递时间限制,因此每次都不会重新评估它,另外我们需要一个虚拟参数y
,因为它会尝试将此条件应用于迭代的结果,但我们并不真的想要那个,因为那是.z.Z
。每次迭代时,它都会评估.z.Z
返回日期时间。由于您使用的是\
而非/
,因此您将获得整个列表。
q)f2:{{.z.Z}\[{y; .z.T<x}.z.T+1e3*x; .z.Z]}
q)f2 1
2014.04.30T17:40:23.357 2014.04.30T17:40:23.357 .......
话虽如此,如果你想要生成一系列日期时间值,从现在到现在+ x,这不是最好的方法,因为你的.z.Z
标记将反映它的时间让你的机器实际评估它。
校正:
我没有正确解释我们测试lambda的条件是{y; .z.T<x}.z.T+1e3*x
的原因。您希望确保仅在开始时评估.z.T+1e3*x
,因此您不希望绑定在函数内部。此外,如果您遗漏了y
参数,那么{z.T<x}.z.T+1e3*x
将立即评估为false,并且当您尝试将迭代结果应用于{时,您的迭代将返回type
错误{1}}在循环的每个循环中。通过保留0b
而不使用它,我们确保延迟此评估并创建一个正确测试我们边界的lambda。
答案 2 :(得分:1)
.z.T
是time
数据类型中的当前时间; time
s中的基础数字是自午夜以来的毫秒数,因此添加1000*x
将来会有x
秒的时间。
-1 string .z.Z
将当前datetime
打印到stdout
。
while[(.z.T < yr); ..]
循环,只要当前时间小于yr
(将来x
秒)。
ZZ,::.z.Z
将当前datetime
附加到名为ZZ
的全局变量。
一些额外的说明:
datetime
数据类型通常已被弃用,有利于timestamp
。
测试条件周围的括号是多余的。
第二个:
也是多余的,但出于更有趣的原因:,:
(就像所有的两个参数&#34;回写&#34;函数(x+:1
,{ {1}}等))总是修改全局变量或局部变量,具体取决于函数中是否存在该名称的本地变量。
证明:
y-:2
在该函数版本的while循环中被修改的q)delete from`.;
q){ZZ:(); yr:.z.T+1000*x; -1 string .z.Z; while[(.z.T < yr); ZZ,::.z.Z]}1
2014.04.30T18:26:24.592
q)ZZ
'ZZ
q)
是在第一个语句中声明的局部变量,而不是一个全局的,因为如果存在ZZ
,可能会假设修改声明。
无论如何,如果你想这样做,至少应该重写为::
。
答案 3 :(得分:0)
此功能正在做什么:
这个函数接受一个参数(应该是int)并将这些参数添加到当前时间(假设它将来是时间)。然后它从当前时间到未来时间开始循环,并在每次迭代中,将当前日期和时间附加到全局列表(由变量ZZ引用)。
如何致电:yr[2]
<强>解释强>
yr:.z.T+1000*x
.z.T
为您提供当地时间。
1000相当于1秒。因此它将x秒添加到当前时间并将其存储在变量yr中。 (:
表示赋值(=))
ZZ,::.z.Z
::
用于为全局变量赋值。所以ZZ
是一个
列表的全局变量(如数组)。
,
用于追加。上述陈述相当于ZZ : ZZ , .z.Z
.z.Z
提供当前的当地日期和时间。
while[(.z.T < yr);...]
这是循环的条件。所以需要当前时间(.z.T
)
并检查它是否小于计算的未来时间
在第一个声明中。
循环将在当前时间=年(未来时间)结束。
ZZ
。