Almost everything is an object (and everything is almost an object!)

by David Black on September 27, 2010

Almost everything is an object

(and everything is almost an object!)

This guest post is contributed by David A. Black, a Senior Developer with Cyrus Innovation, Inc. David has been programming in Ruby for ten years, and is the author of The Well-Grounded Rubyist (Manning, 2009). He’s one of the founding directors of Ruby Central, Inc., the parent organization of the International Ruby Conference (RubyConf). David is also one of the most experienced Ruby and Rails trainers in the the business. One of his current projects is The Compleat Rubyist, a training event taught by David, Gregory Brown, and Jeremy McAnally. David is a frequent invited speaker and keynoter at Ruby and Rails conferences, as well as users groups, in the U.S. and abroad.

David A. Black You’ll sometimes hear the statement that Everything is an object in Ruby. But is that true?

It’s almost true, but not quite. No, this doesn’t mean we’ve caught Ruby doing something wrong! It’s just an opportunity to look more closely at how objects operate.

Here’s an example of something that isn’t an object: an argument list. Consider a method call like this:

create_person("David", "Black", "New Jersey")

Three strings are serving as method arguments, and those strings are objects. But the argument list itself is not an object. There’s no ArgumentList class. Moreover, it would be hard to imagine one. Consider this code:

arglist = ArgumentList.new  # no such thing; a thought experiment!
arglist << "David"
arglist << "Black"
arglist << "New Jersey"

Already there’s a problem. The << “operator” is actually a method. That means that the code we’ve got is equivalent to this:

arglist = ArgumentList.new
arglist.<<("David")
# etc.

So in order to use an ArgumentList object, we need to be able to construct… an argument list.

The way out of this circularity is to include something in the language that isn’t an object. Argument lists are part of the syntax of the language. They’re not objects.

In addition to syntactic constructs like argument lists, Ruby also includes non-objects in the form of keywords like if, class, alias, and begin, end, rescue. Some of these keywords provide control flow techniques; some, like alias, let you conduct business with the interpreter that affects the world in which your objects live. Non-object keywords help to create the framework inside of which your objects can come into being and do everything they have to do.

So not everything is Ruby is an object, and for good reason. But there’s a corollary to this point, and an important one: even though not everything is an object, everything does evaluate to an object.


New to Ruby? Join our online Core Ruby course. Read details here.


Everything (really, everything!) evaluates to an object

Every Ruby statement or expression evaluates to a single object. This is true not only of variables, object literals, and method calls, but of control-flow structures, keyword-based statements, class and method definitions, and everything else. The object a statement evaluates to may be nil, but it will always be something. Understanding this principle can help you make sense of things that happen in your code, and also provides some techniques you can take advantage of.

You can get lots of information about how statements evaluate to objects by using irb. irb is very literal-minded, and will always print out the value of the statement you type in. Sometimes the value is obvious; sometimes what irb shows you is instructive. Let’s start with an irb classic: puts.

>> puts "Hi"
Hi
=> nil

Note the nil at the end: that’s the return value from puts. After all, puts is a method, so it has to return something. As it happens, it always returns nil. The printing out of the string is a side-effect.

Knowing that puts returns nil will help you predict the result of evaluating this code:

["one", "two", "three"].map {|n| puts n.upcase }

It’s a common learner mistake to expect the result to be ["ONE", "TWO", "THREE"]. In fact, it’s [nil, nil, nil]. Each time through the block, the block evaluates to the return value of puts—namely, nil.

If every statement reduces to a single object, then the principle must apply to things you probably don’t usually think of in this way, such as class definitions. Sure enough:

>> class MyClass; end
=> nil

An empty class definition body evaluates to nil. A non-empty class definition body evaluates to the last expression evaluated inside it:

>> class AnotherClass
>>   2 + 3
>> end
=> 5

You can, if you want to, assign this value to a variable:

>> x = class C; "Hi!"; end
=> "Hi!"
>> puts x
Hi!
=> nil

It’s kind of silly to do that, usually. But there’s one very common idiom that uses this technique. Remember that inside a class body, self is the class object itself:

>> class Thing
>>   self
>> end
=> Thing

You’ll often see this fact used for the purpose of grabbing hold, in a variable, of an object’s singleton class:

>> t = Thing.new
=> #<Thing:0x18cf18>
>> singleton_class_of_t = class << t; self; end
=> #<Class:#<Thing:0x18cf18>>

We go into the singleton class using the class << t construct, evaluate self, and exit the class body. The result of this fishing expedition is that we’ve landed the singleton class itself and saved it to a variable. Now it’s possible to do things with the class that you can’t do as long as it remains anonymous, such as calling class_eval on it.

(Note that in Ruby 1.9.2 there’s a singleton_class method, so the above technique is probably going to start disappearing as more people move to 1.9.2 and higher versions.)

Most class bodies evaluate to nil because, typically, class definitions end with a method definition—and method definitions always evaluate to nil:

>> def my_method
>>   "Doesn't matter what I put here"
>> end
=> nil

Of course, when you call the method it returns a string:

>> my_method
=> "Doesn't matter what I put here"

But the method definition itself evaluates to nil.

Conditionals, including if statements and case statements, also always evaluate to an object. This isn’t exactly an obscure point; after all, the ultimate value of a conditional is often put to use.

>> action = "stop"
=> "stop"
>> message = if action == "stop" then "Bye!" else "Continue!" end
=> "Bye!"

There’s an interesting general rule, though: If no condition is true, or no case matched, then an if statement or case statement always evaluates to nil.

>> if 3 > 5
>>   "Universe is in trouble!"
>> end
=> nil

>> case 1 + 1
>> when 3
>>   "My world is upside-down!"
>> end
=> nil

One place you’ll see this put to use is in templating situations where someone wants to include something conditionally. Consider this erb fragment:

<%= "#{first} #{"#{middle} " if middle}#{last}" %>

The expression "#{middle }" if middle will evaluate to nil if middle is nil. Interpolating nil into a string is the same as interpolating an empty string, so that whole part of the larger string will simply be an empty string. If middle isn’t nil, then middle plus a space will be interpolated into the larger string. Mind you, if you actually use this technique, people might accuse you of having overly clever or “cute” code—and they may be right! But even if you don’t use it in real code, it’s an instructive example.

So even though not everything is an object in Ruby, an object is never very far away. Every statement eventually reduces to a single object. You might say that almost everything is an object—and everything is almost an object. Much of the time, the objects produced by control flow statements, class and method definitions, and keyword statements are ignored. But when you want or need them, they’re available. And exploring what statements evaluate to can teach you a lot about what Ruby is “thinking”.

Post supported by Zencoder Inc.: Zencoder does video encoding, as a service, in the cloud. Hook up to their API, and within minutes, you’ll be ready to process video, whether it’s 10,000 videos or just 10. Zencoder is highly optimized for speed, uses the best compression technology around, and handles hundreds of video/audio formats (including obscure and corrupt files). Also check out their open-source HTML5 video playerVideoJS.

Do read these awesome Guest Posts:

Technorati Tags: , , , ,

Posted by David Black

{ 6 comments… read them below or add one }

Allen Madsen September 27, 2010 at 6:48 pm

I’m not so sure I would say the argument list isn’t an object. You can think of the splat operator as saying I want to pass in the argument list instead of the individual arguments. In that case you example could be rewritten as:

arglist = Array.new
arglist << "David"
arglist << "Black"
arglist << "New Jersey"

def foo(first, last, city)
puts first, last, city
end

foo(*argslist)

Also, within the method you can also reference the arguments list. For example:

def foo(*args)
puts "The arguments passed in are: #{args}"
end

Reply

Jean Hugues Robert September 28, 2010 at 2:54 am

It is becoming important to distinguish “objects” from “values”, not everything is nor need to be an object. See http://virteal.com/ObjectVersusValue

Reply

David A. Black September 28, 2010 at 1:14 pm

Thanks for the interesting article, though the link you gave didn’t work; I looked it up and found it here.

(Hopefully that will come out OK in the comment body :-)

I’ve often heard Ruby’s argument-passing semantics described (by myself and others) as “pass by value, where the values happen to be references to objects”. I think that accounts for most of it sans paradox, though there’s some normalization going on implicitly when you use, say, a literal string as an argument rather than a variable containing a reference to a string.

An interesting case also is (are?) the “immediate valus” like symbols and integers where there’s no reference involved. But since Ruby sort of discounts one level of reference, that’s transparent; as programmers we don’t have to know that if x is a symbol, it’s being handled a bit differently from an array or string or file handle.

It’s interesting that you see some of the semantic/method hooks, like == (and maybe to_s?) as awkward or a kind of attempt at glue between object and value. I tend to see them as a very consistent, elegant way to expose object-specific semantics to the engineering side of the task, so to speak, in return for making the object/value distinction more or less go away. Ruby seems to me to be very much about this, with the most vivid example probably being the case statement: any object that defines === (and they all do, since it’s in Object) can serve as a “when” condition; the === method can be fine-tuned to mean anything; and in actually usage the object-oriented/message-sending semantics essentially disappear.

(In fact, to me one sign of how nicely the === thing is designed is that whenever I see === used explicitly (like, “if String === obj), it looks very strange :-)

Reply

Jean Hugues Robert September 28, 2010 at 6:27 pm

It is very true, as you said, that Ruby makes the distinction more or less go away. This is often convenient.

However, and this is my main point, I think that Ruby could help more to educate people about the benefits of the value semantic (like immutability for example). Functional programming has a bright future, I would be sad if Ruby was not part of that future.

So, I would be happy if for example there where a sub class of Object named Value, a sub class that would be the root class for all objects that are immutable (or even a mixin, for cases when an object becomes immutable, freeze style).

This is fairly academic however, Ruby is very nice already.

Thanks for the feedback.

Jean Hugues

Reply

Grégory Horion July 26, 2012 at 6:56 pm

i think this little schema will make everybody happy :) http://cl.ly/image/463K3z0n0e3f

Reply

magneto12321 March 13, 2014 at 5:15 am

Terminology invoking “objects” and “oriented” in the modern sense of object-oriented programming made its first appearance at MIT in the late 1950s and early 1960s. In the environment of the artificial intelligence group, as early as 1960, “object” could refer to identified items (LISP atoms) with properties (attributes);[8][9] Alan Kay was later to cite a detailed understanding of LISP internals as a strong influence on his thinking in 1966.[10] Another early MIT example was Sketchpad created by Ivan Sutherland in 1960–61; in the glossary of the 1963 technical report based on his dissertation about Sketchpad, Sutherland defined notions of “object” and “instance” (with the class concept covered by “master” or “definition”), albeit specialized to graphical interaction.[11] Also, an MIT ALGOL version, AED-0, linked data structures (“plexes”, in that dialect) directly with procedures, prefiguring what were later termed “messages”, “methods” and “member functions”.[12][13]

The formal programming concept of objects was introduced in the 1960s in Simula

If everything is an object, then really nothing is.

Really it’s not even the first fully object oriented language. Actually, a virtual machine like the JVM is basically object style assembler.

Some people are obsesses with syntactic sugar.

Reply

Leave a Comment

{ 52 trackbacks }

Previous post:

Next post: