¿Cuál es la diferencia entre STDIN y $ stdin en Ruby?

Ruby tiene dos formas de referirse a la entrada estándar: la constante STDIN y la variable global $stdin .

Aparte del hecho de que puedo asignar un objeto IO diferente a $stdin porque no es una constante (por ejemplo, antes de bifurcar para redirigir IO en mis hijos), ¿cuál es la diferencia entre STDIN y $stdin ? ¿Cuándo debería usar cada uno en mi código?

Si reasigno $stdin , ¿afecta a STDIN ?

¿Y esto también se aplica a STDOUT / $stdout y STDER / $stderr ?

Si se reasigna $stdin , STDIN no se ve afectado. Del mismo modo $stdin no se ve afectado cuando se reasigna STDIN (lo cual es perfectamente posible (aunque sin sentido), pero producirá una advertencia). Sin embargo, si ninguna de las variables ha sido reasignada, ambas apuntan al mismo objeto IO, por lo que reopen a reopen ¹ en una afectará a la otra.

Todos los métodos incorporados de ruby ​​usan $< (también ARGF como ARGF ) para leer la entrada. Si ARGV está vacío, ARGF lee desde $stdin , por lo que si reasigna $stdin , eso afectará a todos los métodos integrados. Si reasigna STDIN no tendrá ningún efecto a menos que algún método de terceros use STDIN .

En su propio código, debe usar $stdin para ser coherente con los métodos integrados².

¹ reopen es un método que puede redirigir un objeto IO a otra secuencia o archivo. Sin embargo, no puede usarlo para redirigir un IO a un StringIO, por lo que no elimina todos los casos de uso de la reasignación de $stdin .

² Por supuesto, también puede usar $< / ARGF para ser aún más consistente con los métodos integrados, pero la mayoría de las veces no desea el comportamiento de ARGF si está usando explícitamente la stream stdin.

STDERR y $ stderr apuntan a lo mismo inicialmente; puede reasignar la variable global, pero no debe meterse con la constante. $ stdin y STDIN, $ stdout y STDOUT son iguales.

Tuve que cambiar STDERR un par de veces como alternativa al parche de mono que algunas gems generaban mensajes de error con STDERR.puts. Si reasigna con STDERR = $ stdout, recibirá una advertencia, mientras que STDERR.reopen (‘nul’, ‘w’) es evidente.