Ruby has two ways of referring to the standard input: The STDIN constant , and the $stdin global variable.
Aside from the fact that I can assign a different IO object to $stdin because it’s not a constant (e.g. before forking to redirect IO in my children), what’s the difference between STDIN and $stdin? When should I use each in my code?
If I reassign $stdin, does it affect STDIN?
And does this also apply to STDOUT/$stdout and STDER/$stderr?
If
$stdinis reassigned,STDINis not affected. Likewise$stdinis not affected whenSTDINis reassigned (which is perfectly possible (though pointless), but will produce a warning). However if neither variable has been reassigned, they both point to the same IO object, so callingreopen¹ on one will affect the other.All the built-in ruby methods use
$<(a.k.a.ARGF) to read input. IfARGVis empty,ARGFreads from$stdin, so if you reassign$stdin, that will affect all built-in methods. If you reassignSTDINit will have no effect unless some 3rd party method usesSTDIN.In your own code you should use
$stdinto be consistent with the built-in methods².¹
reopenis a method which can redirect an IO object to another stream or file. However you can’t use it to redirect an IO to a StringIO, so it does not eliminate all uses cases of reassigning$stdin.² You may of course also use
$</ARGFto be even more consistent with the built-in methods, but most of the time you don’t want theARGFbehavior if you’re explicitly using the stdin stream.