A Deep Dive Into the Ruby Puts Method
Most programmers are familiar with the traidition of the “Hello World” program. New programmers use it as their first program. Experienced programmers use it to prove that their new project can run correctly.
Ruby makes “Hello World” trivially easy:
1
|
|
The puts
method is one of the workhorses of the ruby core library.
It is the most common of the methods in the IO module.
But what is actually going on here?
The method signature of puts
is as follows:
1
|
|
That is, puts
takes zero or more objects and returns nil.
Puts is defined in the IO core class1. This class ships with the core of ruby and provides ‘the basis for all input and output in ruby’ 2.
When you call puts
without an explicit context, as with the hello world program, the method call is delegated through the main
object that exists at the top level of all ruby programs to an IO object that is bound to the standard input and standard output.
Ruby provides constant objects STDOUT
, STDIN
, and STDERR
by default, which are all IO objects bound to the appropriate ‘files’3.
Hence, the two lines are functionally equivalent:
1 2 |
|
Where is puts
defined? Like many of the core ruby classes, IO
is defined directly in the underlying C code.
The current source of the IO
code can be found in io.c.
puts
is actually defined in two places; once using the rb_define_method
C function to associate the rb_io_puts
C function with the puts
method on the ruby IO class, found around line 12187 in io.c
.
puts
is also defined with the rb_define_global_function
C function on line 12106, to associate a special version of puts
, rb_f_puts
, with the ruby Kernel class.
These methods provide the actual functionality of puts
, which is a thin wrapper around the more basic write
method.
Puts provides the following functionality:
If puts is called with no arguments, it will print a newline character.
If puts is provided arguments, then, for each argument, if it is an object, call
.to_s
on the object and print the result, adding a newline if it does not end in a newline.Any arguments passed that are arrays will have
puts
called on each element of the array.
The last bit means that calling puts
on nested arrays will print each element of each array with .to_s
on a separate line.
To print an array in the format to which you are accustomed to defining them, use .to_s
on the array explicitly.
The fact that puts
will not add a newline if the string to be printed already ends in a newline is worth noting.
Because of this functionality, the following lines are equivalent, which can be an issue when debugging:
1 2 |
|
Happy Coding!