Difference Between Stdin and $Stdin in Ruby

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

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.

Difference between `STDIN` and `$stdin`

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.

Difference between $stdin and others gets.chomp

When invoking gets without specifying the stream, we are invoking Kernel#gets and when stream is specified we are invoking IO#gets

I believe Kernel#gets wraps around IO#gets under the hood but before it needs to create an IO object, that IO object will be a concatenation of all command line arguments(ARGV) ( it will try to open every single one as file in positional order) and them read from it. If there are no elements left on ARGV it will then read from stdin.

That behavior can be tested with this simple snippet:

while gets
puts $_
end

When running ruby myscript.rb without parameters it will read stdin, if parameters are specified it will try to open as files and read from it, it will works similarly to cat command .

That stream could be tty, socket, file etc:

stream = File.open('/etc/passwd','r')

puts stream.gets

stream.close

A simple http client using sockets:

require 'socket'

s = TCPSocket.new 'icanhazip.com',80

s.puts <<~EOF
GET / HTTP/1.1
Host: icanhazip.com

EOF

while line = s.gets
puts line
end

s.close

More about Kernel#gets here

More about IO#gets

What's the difference between gets.chomp() vs. STDIN.gets.chomp()?

gets will use Kernel#gets, which first tries to read the contents of files passed in through ARGV. If there are no files in ARGV, it will use standard input instead (at which point it's the same as STDIN.gets.

Note: As echristopherson pointed out, Kernel#gets will actually fall back to $stdin, not STDIN. However, unless you assign $stdin to a different input stream, it will be identical to STDIN by default.

http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-gets

Is there any difference between $stdin.gets and gets?

gets is Kernel#gets, it first tries to read the contents of files passed in through ARGV. If there are no files in ARGV, it will use standard input instead (at which point it's the same as $stdin.gets)

Ruby: What's the difference between STDIN.gets() and gets.chomp()?

Easiest way to do what you describe here is Integer(gets), since Integer() ignores the trailing newline, so chomp is unnecessary. There's also no need explicitly specify STDIN as the receiver, as that's what Kernel#gets will do if there are no arguments to the script.

Difference between $stdout and STDOUT in Ruby

$stdout is a global variable that represents the current standard output. STDOUT is a constant representing standard output and is typically the default value of $stdout.

With STDOUT being a constant, you shouldn't re-define it, however, you can re-define $stdout without errors/warnings (re-defining STDOUT will raise a warning). for example, you can do:

$stdout = STDERR

Same goes for $stderr and STDERR


So, to answer the other part of your question, use the global variables to redirect output, not the constants. Just be careful to change it back further on in your code, re-defining global variables can impact other parts of your application.

Ruby: What Does STDIN.gets mean?

If you run p STDIN.method(:gets) you get #<Method: IO#gets>. This means that the gets method if defined in the IO module. Knowing that, you can then read the official documentation of gets here:

http://ruby-doc.org/core-2.3.0/IO.html#method-i-gets

The gets method does not store its data in some default place, it returns it as the return value of the method. If that return value is being ignored, then the data is lost, but it could still be useful to call STDIN.gets for its side effects: gets will pause the execution of your thread and wait for input from the standard input. This would give the user a chance to review what the Ruby script has already done and terminate it early if the user wants to.



Related Topics



Leave a reply



Submit