Enumerable#take_while
は、公式リファレンスによると
Enumerable オブジェクトの要素を順に偽になるまでブロックで評価します。 最初に偽になった要素の手前の要素までを配列として返します。
というメソッドです。
つまり、たとえば戻り値が長さ4の配列だった場合、5つ目の要素までeachで評価しているということになるわけです。
普通はそれで問題ないわけですが、IOオブジェクトのようにeachメソッドに副作用があると少し変わってきます。
IO#each
は1行ごとに読んでポインタを進めますから、以下のようなことが起こります。
$ seq 1 10 | ruby -e 'p $stdin.take_while {|i| i.to_i < 5}; p $stdin.gets'
["1\n", "2\n", "3\n", "4\n"]
"6\n"
seq 1 10
で1から10までの数字を1行ずつRubyの標準入力に渡しています。
最初のtake_whileで1から4までを取ったので、次のgetsでは5が得られるような気がするんですが、5はtake_whileで読み込まれて捨てられているので、次の6が出力されます。