Я немного поэкспериментировал и выяснил, что происходит.Как вы, возможно, знаете, два потока Ruby не могут работать одновременно;они просто быстро переключаются назад и вперед. * Обычно, если вы вызываете gets
, вызывающий поток будет ожидать ввода, а другие потоки будут продолжаться (поскольку gets
освобождает GIL ).Однако в irb (по крайней мере, в Mac OS X) другие потоки не продолжают выполняться, пока он ожидает ввода.Пример:
>> i = 0
=> 0
>> Thread.new { loop { i += 1 } }
=> #<Thread:0x1094d6d68 run>
>> i
=> 234866
>> i
=> 401271
Если бы поток выполнялся, i
было бы в миллионах.(Протестировано вне irb.) Кроме того, ruby использовал <1% CPU. </p>
В вашем примере, каждый раз, когда вы нажимаете enter, поток получает долю секунды для выполнения - достаточно времени, чтобы записать число илиновая строка.Затем ruby переключается обратно на поток irb, который записывает приглашение и ожидает ввода.
* В JRuby, IronRuby и Rubinius 2.0 несколько потоков могут работать одновременно.
Edit: Я тестировал на Windows, и там продолжают работать потоки.Если вы хотите, чтобы потоки продолжали работать на Mac, вы можете сохранить это как, скажем, sirb.rb (простой irb) и использовать его вместо irb:
$stdout.sync = true
while true
print "> "
p(eval gets)
end
Обратите внимание, что, в отличие от irb, он не 't не поддерживает оператор, занимающий несколько строк, и не поддерживает перемещение каретки для редактирования или нажатие кнопки «Вверх» для истории (в Mac OS X).Пример:
> for i in 1..10; print i ** 2, " "; end; puts
1 4 9 16 25 36 49 64 81 100
nil