crystal
crystal copied to clipboard
Improving nested eachs (loops)
As you can see in this sample from the repo, it pretty common to need nested eachs, wouldn't it be nice to have a method this like showed below?
(0...9).nest((0...9)).nest((0...9)).each do |i, j, k|
...
end
Or maybe you come up with a better solution, the thing is, I'm sure we can improve this kind of nested loops.
(0...9).to_a.each_cartesian((0...9).to_a, (0...9).to_a) do |(i, j, k)|
# ...
end
@HertzDevil Wouldn't that be way more memory consuming for larger ranges?
If performance really does matter, you could use a macro:
macro each_many(*exprs, &block)
{% for expr, i in exprs %}
%iter{i} = {{ expr }}
{% end %}
{% for expr, i in exprs %}
%iter{i}.each do |{{ block.args[i] }}|
{% end %}
{{ block.body }}
{% for expr, i in exprs %}
end
{% end %}
end
each_many(0..2, 0..3, 0..4) { |i, j, k| p [i, j, k] }
This assumes #each
never invalidates the receiver, so it doesn't work if e.g. one of the expressions is a Char::Reader
or Dir
.
I don't think such a macro would belong in the standard library since it provides little advantage over, well, nesting the loops manually (the number of expressions must be known at compile-time).