Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Ruby use $stdout for writing the output of puts and return?

Tags:

ruby

irb

pry

I want to know the output stream being used by Ruby to print these things at the command-line:

irb(main):001:0> a="test"
=> "test"
irb(main):002:0> puts a
test
=> nil
irb(main):003:0> a
=> "test"

Is $stdout used for irb(main):002:0> and irb(main):003:0>? And, is there any change in the value of $stdout between those two invocations?

Also, can some one point me to the Ruby source from where these things get printed/written?

like image 562
Keyur Shah Avatar asked Jan 24 '14 22:01

Keyur Shah


People also ask

IS puts a return in Ruby?

Everything in Ruby has a return value! You may notice that the puts and print methods, when run in IRB, print values on the screen and then display a line like this: => nil . This is because puts and print may print the value you want, but instead of returning that value, they return nil .

What is the difference between puts and return in Ruby?

puts(string) in ruby writes the string value into $stdout . For example if you run ruby console in terminal, string will be written into your terminal. At the same time every method in ruby returns something and method puts returns nil .

How do I get output in Ruby?

Ruby has another three methods for printing output. In the example, we present the p , printf and putc methods. The p calls the inspect method upon the object being printed. The method is useful for debugging.

What is PP in Ruby?

A pretty-printer for Ruby objects.


1 Answers

Yes. And it's easy to test/prove to yourself. Try this at the command-line:

ruby -e 'puts "foo"' > test.out
cat test.out

The output will be:

foo

Ruby uses the STDOUT channel to output to the console. The OS then redirects that STDOUT to "test.out".

Try it with:

ruby -e 'STDOUT.puts "foo"' > test.out

and you'll get the same result.

If we do:

ruby -e 'STDERR.puts "foo"' > test.out
foo
cat test.out

You'll see nothing in the file, but "foo" will have been written to the console on the STDERR channel.

Ruby defines $stdout as a global you can change, and STDOUT as a constant, which you shouldn't change. Similarly, $stderr and STDERR are available.

Now, here's where it gets fun, and proves your question. Try this:

ruby -e '$stdout = STDERR; puts "foo"' > test.out

and you'll have the same results as when I output to STDERR, because, at puts was using the value for $stdout to select the output stream, and wrote to STDERR. Those stream values are picked up by Ruby from the OS when the interpreter starts, and are remembered during the run-time of the script. You can change them if necessary and Ruby will forget those settings when the interpreter exits, and reset itself to its normal state the next time.

You shouldn't rely on the implied/invisible behavior of changing $stdout though, because that leads to REALLY confusing code. Instead, I'd strongly recommend using an explicit STDERR.puts any time you're writing to STDERR and a bare puts for normal output to STDOUT. If you're intermingling output to both, then it'd probably be clearer to use STDOUT.puts and STDERR.puts, but that's your call.

Now, IRB is the same as a regular script running in the interpreter is, as far as using $stdout so writing output in IRB to $stdout works the same:

irb(main):001:0> $stdout
#<IO:<STDOUT>>
irb(main):002:0> $stderr
#<IO:<STDERR>>

And:

irb(main):003:0> $stdout.puts 'foo'
foo
nil
irb(main):004:0> $stderr.puts 'foo'
foo
nil

And finally:

irb(main):007:0> $stdout.isatty
true
irb(main):008:0> $stdout.isatty
true

We can't really tell any difference until we look a little lower; They're both TTY channels, with the standard STDOUT and STDERR channel numbers:

irb(main):009:0> $stdout.fileno
1
irb(main):010:0> $stderr.fileno
2

Hopefully that helps 'splain it.


I just realized that IRB's reporting of the return value of puts might be confusing you, causing you to think that the STDOUT is changing. That nil is returned has nothing to do with STDOUT or STDERR. It's because puts returns nil, which is dutifully reported by IRB.

like image 82
the Tin Man Avatar answered Oct 02 '22 03:10

the Tin Man