3

I wonder if there is any real difference between STDIN and $stdin. I do in irb:

STDIN == $stdin

and get back true. Are they just two names for the same thing? Or is there some difference?

sawa
  • 165,429
  • 45
  • 277
  • 381
SuperManEver
  • 2,263
  • 6
  • 28
  • 36
  • possible duplicate of [What is the difference between STDIN and $stdin in Ruby?](http://stackoverflow.com/questions/4279604/what-is-the-difference-between-stdin-and-stdin-in-ruby) – shivam Apr 22 '15 at 12:47

2 Answers2

4

From Ruby globals:

STDIN

The standard input. The default value for $stdin.

They are the same object by default.

[1] pry(main)> $stdin.object_id
=> 13338048
[2] pry(main)> STDIN.object_id
=> 13338048
[3] pry(main)> $stdin.object_id == STDIN.object_id
=> true

As @shivam commented, $stdin is a global variable and it may be assigned to something different, while STDIN is a constant.

Community
  • 1
  • 1
Arie Xiao
  • 13,909
  • 3
  • 31
  • 30
3

STDIN is a constant and therefore you'll get a ruby warning if you try to replace it. Otherwise the two are just normal ruby variables in that they can point to the same object (and are by default) and if they do, doing something with one will affect the other variable, but if you assign something else to one of the variables, they will be different.

Standard ruby methods like get will read from $stdin (not STDIN) by default. That means you can override $stdin ($stdout, $stderr) for standard methods and use the constant versions to see what $stdin, $stdout or $stderr originaly were.

Note that overriding $stdin, $stdout, or $stderr won't affect the standard streams of newly spawned programs (the actual filedescriptors 0, 1, and 2 respectively). To do that you'd need to call IO#reopen on the stream you'd want to change, e.g. (assuming the constant version hasn't been forcibly replaced),

STDOUT.reopen("newfile") #Write all output to "newfile" including the output of newly spawned processes (`%x{}`,`system`, `spawn`, `IO.popen`, etc.)

Now with reopen, you can replace the streams only to actual OS-level files/file descriptors (e.g., no StringIO), but if you're on UNIX, there's not much you can't do with OS-level files (you can change them to pipes which you can read elsewhere in your program, for example).

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142