В чем разница между STDIN и $stdin в Ruby?
У Ruby есть два способа обращения к стандартному вводу: STDIN
постоянная, а $stdin
глобальная переменная.
Помимо того, что я могу назначить другой IO
Возражать $stdin
потому что это не константа (например, перед тем, как разветвить перенаправить ввод-вывод у моих детей), какая разница между STDIN
а также $stdin
? Когда я должен использовать каждый в моем коде?
Если я переназначу $stdin
, это влияет STDIN
?
И это также относится к STDOUT
/$stdout
а также STDER
/$stderr
?
2 ответа
Если $stdin
переназначен, STDIN
не влияет. также $stdin
не влияет, когда STDIN
переназначается (что вполне возможно (хотя и бессмысленно), но выдаст предупреждение). Однако, если ни одна переменная не была переназначена, они обе указывают на один и тот же объект ввода-вывода, поэтому reopen
¹ на один повлияет на другой.
Все встроенные методы ruby используют $<
(ака ARGF
) читать ввод. Если ARGV
пустой, ARGF
читает из $stdin
так что если вы переназначаете $stdin
, что повлияет на все встроенные методы. Если вы переназначаете STDIN
это не будет иметь никакого эффекта, если какой-либо сторонний метод не использует STDIN
,
В вашем собственном коде вы должны использовать $stdin
соответствовать встроенным методам².
¹ reopen
это метод, который может перенаправить объект ввода-вывода в другой поток или файл. Однако вы не можете использовать его для перенаправления ввода-вывода в StringIO, поэтому он не исключает все случаи повторного назначения $stdin
,
² Конечно, вы также можете использовать $<
/ARGF
чтобы быть еще более совместимым со встроенными методами, но в большинстве случаев вы не хотите ARGF
поведение, если вы явно используете поток stdin.
STDERR и $stderr изначально указывают на одно и то же; Вы можете переназначить глобальную переменную, но не следует связываться с константой. Пары $stdin и STDIN, $stdout и STDOUT аналогично.
Мне пришлось пару раз менять STDERR в качестве альтернативы мартовскому исправлению некоторых драгоценных камней, выводящих сообщения об ошибках с помощью STDERR.puts. Если вы переназначаете STDERR = $stdout, вы получите предупреждение, тогда как STDERR.reopen ('nul', 'w') само собой разумеется.