Avoid Conditionals
K has a conditional construct (:[
) which is equivalent to a Lisp-style cond
:
:[cond1;result1; cond2;result2; cond3;result3; default]
You can have as many conditions as you like, and if none match the default value is returned.
Sometimes (as in recursive programs or programs that otherwise rely on a sequence of side effects), there's no getting around using one of these. However, in situations where you can afford to do a bit of extra work, you can often replace a "cond" with list indexing.
Consider the infamous fizzbuzz program. Written in a conventional imperative programming style, we might go with:
{:[~x!15;"FizzBuzz";~x!3;"Fizz";~x!5;"Buzz";x]}'1+!100
There's quite a bit of repetition here in the divisibility tests. A different approach recognizes that there are 4 cases (a number, divisibility by only 3, divisibility by only 5, divisibility by 3 and 5) and attempts to directly compute an index which chooses one of these cases from a list:
{(x;"Fizz";"Buzz";"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100
Two characters shorter, and a better use of the language. Knowing that list literals are evaluated right to left, we also gain some additional golfing opportunities for combining reused subexpressions. We couldn't have easily done this in the cond-based version, since the string cases aren't evaluated at all if they aren't selected:
{(x;4#t;4_ t;t:"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100
Now we've saved 5 characters overall. Incidentally, this particular example works out even nicer in k5, since we have the "pack" overload for /
to handle the step of multiplying by a vector of coefficients and summing:
{(x;4_t;4#t;t:"FizzBuzz")@2 2/~3 5!\:x}'1+!100
Also note that the behavior of "find" (?
), which produces an index past the end of the key list if the item is not found, is specifically designed to support handling a "default" case in this kind of indexing. Consider this fragment to convert vowels to uppercase:
{("AEIOU",x)"aeiou"?x}'
Versus one of:
{t:"aeiou"?x;:[t<5;"AEIOU"t;x]}'
{:[~4<t:"aeiou"?x;"AEIOU"t;x]}'
(I know which I'd rather read, too!)