避免有条件
K有一个条件构造(:[
),它等效于Lisp样式cond
:
:[cond1;result1; cond2;result2; cond3;result3; default]
您可以根据需要设置任意多个条件,如果没有条件匹配,则返回默认值。
有时(例如在递归程序或以其他方式依赖一系列副作用的程序中),无法使用其中之一来解决问题。但是,在负担得起一些额外工作的情况下,通常可以用列表索引替换“ cond”。
考虑臭名昭著的fizzbuzz程序。以传统的命令式编程风格编写,我们可能会采用:
{:[~x!15;"FizzBuzz";~x!3;"Fizz";~x!5;"Buzz";x]}'1+!100
在除数测试中,这里有很多重复。一种不同的方法认识到有4种情况(一个数,可除数仅3,可除数5,可除数3和5)并尝试直接计算从列表中选择以下一种情况的索引:
{(x;"Fizz";"Buzz";"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100
缩短两个字符,并更好地使用该语言。知道列表文字是从右到左求值的,我们还获得了一些其他的高尔夫机会,可以将重用的子表达式组合在一起。在基于cond的版本中,我们很难做到这一点,因为如果不选择字符串大小写,则根本不会评估它们:
{(x;4#t;4_ t;t:"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100
现在,我们总共保存了5个字符。顺便说一句,这个特殊的示例在k5中效果更好,因为我们有“ pack”重载/
来处理乘以系数向量和求和的步骤:
{(x;4_t;4#t;t:"FizzBuzz")@2 2/~3 5!\:x}'1+!100
还应注意,“ find”(?
)的行为是专门设计用来支持在这种索引中处理“默认”情况的,如果没有找到该项,该行为会在键列表的末尾产生一个索引。考虑以下片段,将元音转换为大写字母:
{("AEIOU",x)"aeiou"?x}'
与以下之一:
{t:"aeiou"?x;:[t<5;"AEIOU"t;x]}'
{:[~4<t:"aeiou"?x;"AEIOU"t;x]}'
(我知道我也想阅读!)