Ruby is from objects, Perl is from procedures

Perl has had objects for quite a while now, decades even, but you can’t get away from the fact that OO is really just a bag-on-the-side of Perl 5.  This can be a Good Thing sometimes, actually, because it means that well-written code can be used objectively or functionally.

Still, though, Perl 5 is fundamentally not OO at it’s core and all the magic exists in bless().  Ruby (and many others, too many to mention) are object oriented from the ground up.  But what does that really mean?

Quick-and-dirty lesson on Object Orientation

Suppose I had a string, nothing too fancy:

"foo"

How would I figure out the length of that string?  In a classically imperative language (like Perl, C or Pascal) you would call a function and pass the string to that function:

length("foo")

In a textbook-style object-oriented language (Ruby, Smalltalk, etc) we would instead need to assume the string itself know how to figure out it’s own length.  In that case we would call a function on the string itself (a method in OO speak) that would then return the value:

"foo".length

The idea that a piece of data contains everything necessary inside of itself is the fundamental piece of OO theory:  In a sense, the world of Object Oriented languages believes everything is code and there is no difference between data to be acted upon and the thing doing the action.


Objects all the way down

That sounds really impressive, but what does that mean?

Let’s look at our old friend from before, the string:

"foo"

What is that doing?  Well, in a procedural/functional/imperative language, it is creating a data structure of a certain kind (a string) that contains a certain value (the word ‘foo’).  That data structure can then be used or manipulated by other actors (function, procedures and the like) to perform task, but the data itself is technically, fundamentally not useful by itself until it is interpreted by code:


print("foo")

variable = “foo”

return “foo”

The world shifts on it’s axis a little when we move to the land of Objects, though.  Of course, in an OO system, I still could print() the string procedurally, but the major difference is this:

“foo” means: create a new String object with the value of ‘foo’.  So then actual “foo” object then is not, in fact, the value ‘foo’ only, the value is inside the object.

That sounds complicated, right?  There’s an easier way:

Imagine “foo”, our new String object, is a complete computer system itself — a web server in this case.

Just like a web server will only respond to requests it knows how to handle, the object must have the methods and attributes you want.

Just like you could ask “Google.com” for for the page “xyz.html”, you are asking String “foo” for the value of the data stored inside.

And just like Google.com, if you ask for a page it doesn’t have it will give you an error.  If you ask an object to perform a method it doesn’t have you will also get an error.


You are not expected to understand this.

If you have no experience with objects up to now this may sound a little over your head, but you’ll get it.  You’ll have an “Ah-ha” moment.


Symbols: are we ever gonna use this?

Symbols are something that, although not unique to Ruby, have been used to great extent in the Ruby world.

You’ve seen these in every tutorial, in every HOWTO and every Ruby blog post:


:something

:word

:hello

:goodbye

So what are they, and what do you need them for and why would you ever use them.

Symbols go great with a discussion of Object Orientation because they feel a little like something that was invented to fill a gap in the way OO is used in the real world.

Let’s illustrate this with an example Hash table (also called an Associative Array or a Dictionary):

my_hash = { "foo" => "bar" }

In Ruby, the curly-braces denote a hash reference, so in this case we are creating a new hash with one key/value pair and storing it in my_hash.  If I wanted to get a value out of the hash, then, I would do this:

my_hash["foo"]

..which would return me the String “bar”.  Easy peasy, right?  But what does this have to do with symbols and OO?

Remember, everything is an object.  What this means is the hash key (“foo”) is not the text value ‘foo’, it is the whole String object “foo”.  Technically that’s not a problem, but in pure-theory it is since you are using a whole object when what you really need is just a small snippet of data.

Enter symbols.  Symbols are like really, really lightweight strings.  Like, super-model Strings: they can’t do much but they are useful when you need them and they are super-duper skinny.

Of course, like I said before, everything is an object and symbols are not exception.  But all objects are not equal.  Let’s assume we had to objects, a String and a Symbol:

“foo”, :foo

And we then compared how “heavy” they are by the number of methods they each contain:

Symbol: String:

Holy cow, did you see that? String has easily 3-times the methods that symbol does, and that’s the point: if I only care about the textual value then I don’t need all the other baggage that I will never use.


So Symbols are a track-shoe in a world of work boots.  Where do I use them?

The first place new developers see symbols is usually in hashes.  You will see this every-freaking-where in the world of Ruby:

my_hash = { :foo => “bar”, :qux => “quux”, :quuux => “quuuux” }

..and I can then access one of those values thus:

my_hash[:foo]

You you will also see them a lot in method definitions:

def my_method(some_value = :default_value)

Generally, they are used exclusively for internal use only.  This means they are good for being hard-coded in your code, but not something you want to expose to the world


Symbol-isms

Symbols are also a good starting-point for talking about converting one data type in Ruby to another.  Let’s say I had a symbol:

:foo

..but I wanted to use that as a string somewhere?  Remember that list of methods earlier?  One of those methods has the interesting name of “to_s”.  The “S” is for “string”.  This means the symbol object has a method that will return a new String with the symbol text as the string value:

:foo.to_s == “foo”

And it goes both ways.  The String object has a method named “to_sym” (where ‘sym’ means ‘symbol’) and one named “intern” (which is deprecated but used to mean “internalize”).  Knowing this we can also see that:

“foo”.to_sym == :foo

..And remember, here we’re not just comparing the textual values, we’re comparing the actual objects themselves.


Next Time: Evolution of Sigils.  Constants in Ruby, and why Constants sometimes aren’t constant.

  • S Korteling

    Symbols are different from strings because they are immutable and unique: there is only one symbol :the.equal?(:the) is true, “the”.equal?(“the”) is false. Symbols are more lightweight because the program does not have to ‘remember’  lots of different strings with the same content, just one symbol. The number of methods is not very important.

    • Anonymous

      You are of course right – In this case I am simply using method count as a visual way to show the lightweight nature of symbols vs. strings.

  • S Korteling

    Symbols are different from strings because they are immutable and unique: there is only one symbol :the.equal?(:the) is true, “the”.equal?(“the”) is false. Symbols are more lightweight because the program does not have to ‘remember’  lots of different strings with the same content, just one symbol. The number of methods is not very important.

    • xunker

      You are of course right – In this case I am simply using method count as a visual way to show the lightweight nature of symbols vs. strings.