💣
rubyのrangeで終端がnilになると無限ループ
rubyでrangeを作る時、始端や終端をnilにすることができるようなのですが、ループの挙動が面白かったので記事にします。
# 終端のないrange
range = (0..nil)
range.cover? 9999 # true
range.cover? -1 # false
range.each {|n| p n } # 無限ループ(nが表示される)
range.reverse_each {|n| p n } # 無限ループ(何も表示されない)
# 始端のないrange
range = (nil..10)
range.cover? -9999 # true
range.cover? 11 #false
range.each {|n| p n } # RangeError: cannot get the first element of beginless range
range.reverse_each {|n| p n } # RangeError: cannot get the first element of beginless range
今回は終端を動的に取得していてそれがnilが変えるシチュエーションがあり無限ループしました。
(0..children_depth).reduce ...
children_depthが対象のテーブルにレコードが一つもない時nilが返ると言うのを気づかずにハマりました。終端が動的な時は注意が必要かと思います。
reverse_each
はどちらも予想外な感じですね・・・
ソース見てみたけど、ここだけだと不明。ary = enum_to_a(argc, argv, obj);
の中で何かが起こってるのかな?
試したrubyは下記です。
ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc)
Discussion