В чем разница между 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') само собой разумеется.

Другие вопросы по тегам