What is the difference between STDIN and $stdin in Ruby?

ruby, stdin

Solution

If `$stdin` is reassigned, `STDIN` is not affected. Likewise `$stdin` is not affected when `STDIN` is 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 calling `reopen`¹ on one will affect the other.

All the built-in ruby methods use `$<` (a.k.a. `ARGF`) to read input. If `ARGV` is empty, `ARGF` reads from `$stdin`, so if you reassign `$stdin`, that will affect all built-in methods. If you reassign `STDIN` it will have no effect unless some 3rd party method uses `STDIN`.

In your own code you should use `$stdin` to be consistent with the built-in methods².

¹ `reopen` is 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 `$<`/`ARGF` to be even more consistent with the built-in methods, but most of the time you don't want the `ARGF` behavior if you're explicitly using the stdin stream.

Problem

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`?

Original source