How Not to Code

Things That Make Kais ðŸ˜
This is a topic that I feel extremely strongly about, but I think that I’m going to try to write a useful rather than cathartic post here. These are some things that you should always avoid in your code.
each
In other languages, each
or forEach
might be an accepted idiom. It seems like it would be a generically useful iterator. The problem is that it does not have a useful return value: the loop cannot affect the program state without interacting with something outside the loop.
Bad:
array = []
(0..9).each { |i| array << i ** 2 }
array
Good:
(0..9).map { |i| i ** 2 }
As shown, if you want to create a new value with an each
loop, you must declare a temporary value elsewhere, reach outside the loop’s scope, and expend another line after the loop to do something useful with that return value. There are some cases where creating a new value is not important. If you are creating a higher-level iterator, such as map
or reduce
, then you don’t really have an alternative but to use the lower-level iterator. If you are doing metaprogramming, then you probably don’t care that define_method
has a return value. There are a couple other similar situations, but broadly, if you can use a different iterator, do it. And no, I do not mean that you should use times
. It has the same problems.
while
and until
Again, this is a low-level iterator which has more specialized uses than it appears. You should never use either while
or until
when the number of iterations is knowable. If possible, these methods should be wrapped in Enumerator
or Iterator
(Crystal), so that they can be treated as enumerable collections.
class Collatz
include Iterator(Int32)
def initialize
@current = 0
end
def next
@current += 1
collatz(@current)
end
def collatz(n)
steps = 0
until n == 1
n.even? ? (n /= 2) : (n = 3 * n + 1)
steps += 1
end
steps
end
end
for
There are zero reasons to ever use for
loops.
Okay, there seems to be an exception to this rule. There is some sense in which you can use higher-order iterators in Crystal’s metaprogramming, but it can be easiest to use a for
loop. This may change in the future.