What is the object in Ruby's "hello world"?
Asked Answered
O

3

7

If everything is an object in Ruby, to the point that even math operators are methods applied to objects, when I write:

puts "Hello world"

The method is puts, and the parameter is "Hello world", but what is the object?

Otorhinolaryngology answered 29/1, 2017 at 9:57 Comment(2)
Strings are considered objects, so "Hello world" is a string objectTechnics
"Hello world" is an instance of String. String is a subclass of Object. An instance of Object is an object. An instance of String is a specialised object.Jonette
C
11

puts

To find a method, you could call :

method(:puts)
#=> #<Method: Object(Kernel)#puts>

So puts is a method defined in Kernel, available to every Object.

Kernel#puts

puts "Hello world"

is actually

self.puts( String.new("Hello world") )

Where self is the object main.

So puts "hello world" is a :

  • Kernel#puts method call
  • on main
  • with a String object as argument.

Notes

Note that if you execute

self.puts( String.new("Hello world") )

you'll get an error :

private method `puts' called for main:Object (NoMethodError)

Because every Kernel method is made available to every Object, but as a private method. You'd need :

self.send(:puts, String.new("Hello world") )

Test

Another way to check would be :

module Kernel
  def my_puts(*args)
    print "Calling Kernel#my_puts on #{self} with #{args}\n"
    print "Now delegating to Kernel#puts on #{self} with #{args} :\n"
    puts(*args)
  end
end

my_puts "Hello world"

It outputs :

Calling Kernel#my_puts on main with ["Hello world"]
Now delegating to Kernel#puts on main with ["Hello world"] :
Hello world

See? Everything is an object, even though it might not look like it.

2+3

In the same vein : 2+3 is actually Integer(2).+( Integer(3) ).

Computerize answered 29/1, 2017 at 10:7 Comment(0)
L
10

If everything is an object in Ruby,

That is slightly misleading wording. E.g. syntax is not an object, blocks aren't objects, a conditional expression is not an object.

A better phrasing would be: "every value is an object".

to the point that even math operators are methods applied to objects, when I write:

puts "Hello world"

The method is puts, and the parameter is "Hello world", but what is the object?

There are two objects involved. I suspect what you really meant to ask is "what is the receiver object". (Actually, there are many more objects involved, but let's focus on the receiver and the argument for now.)

A message send always has a receiver object, i.e. the object that you send the message to. If the receiver object is not explicitly written out, it is implicitly assumed to be self (a pseudo-variable that always evaluates to the "current object"). Now, the question is: what (or "who") is self here?

This, by the way, is one of the most important questions you should ask yourself when writing Ruby code. Receiverless message sends are to self, instance variables are looked up in self. You should always be aware of which object self is at the point where you are writing your code.

In this particular case, when you write code at what Rubyists call the top-level, self is a pre-defined object Rubyists call main. It doesn't actually have a name, and there is no default reference to it, but 'main' is what it returns when you inspect it or convert it to a string using to_s:

to_s
#=> 'main'

inspect
#=> 'main'

The second object you already correctly identified: it is the String object resulting from the evaluation of the string literal "Hello World".

There are, however, more objects involved here. For example, main is an instance of Object, so Object must exist, too. "Hello world" is an instance of String, String must exist. String and Object are both classes, i.e. objects which are instances of the Class class, so Class must exist. Object's superclass is BasicObject. Class's superclass is Module. Object mixes in Kernel (which is an instance of the Module class). Kernel#puts returns nil, which is an instance of NilClass. Kernel#puts is just a helper method that delegates to IO#puts by calling $stdout.puts.

So, in addition to main and "Hello world", at least the following objects are also involved: nil, NilClass, String, Class, Module, Object, Kernel, BasicObject, IO, and the IO object assigned to the global variable $stdout, representing the standard output stream of your Ruby process.

That's 12 objects which are directly and intimately involved in the execution of your code snippet.

In reality, there are many more objects in even a simple Ruby program:

ruby --disable-gems --disable-did_you_mean -e 'p ObjectSpace.count_objects[:TOTAL]'

On my system, this prints a number around 9780 objects. Now, some of those are the Hash created by ObjectSpace::count_objects and the keys and values inside that Hash (such as the Symbol object :TOTAL), and of course the String created by trying to print out the result. But that's on the order of about ~35 objects, so there's still almost 10000 objects involved in the execution of, well, basically an empty program that does nothing.

Lowndes answered 29/1, 2017 at 11:27 Comment(4)
Yes, I meant "everything" in the sense of "every value", and also "what is the receiver object". I took that "everything" wording from Bruce Tate's excellent book "Seven Languages in Seven Weeks". Thanks for the answer.Otorhinolaryngology
blocks aren't objects Aren't they just disguised Procs?Computerize
@ericduminil no, block are not objects, they are just a piece of bytecode. Unless you materialize the block with & no object is created. You can use my pry-objects gem to validate that.Alonsoalonzo
@Alonsoalonzo : Thanks. Your gem looks good, I'll take a deeper look at it.Computerize
U
1

"Hello world" is the string object defined as a literal constant given as argument to the puts method

puts "Hello world" is in fact a simple way to do

puts myFoo

where myFoo must be a valid object... in your case myFoo = "Hello world"

Utta answered 29/1, 2017 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.