Ruby Stripped, Part 2: Objects

Ruby Stripped, Part 2: Objects

4 Comments

It can’t be said enough: Everything in Ruby is an object. In fact, Ruby is not just an object-oriented programming language, it is probably the object-oriented programming language! All other, including C++, are more of a hybrid, where Ruby is consequent.

You should use that fact to your advantage. People, including me, often use a syntax they know from other languages. That’s ok, because Ruby is intelligent enough to work with that. But it’s not optimized then. If you instead use what Ruby offers, you make use of highly speed-optimized C-compiled code under the hood.

About methods

Let’s have a look at how consequent Ruby indeed is. You probably already know that a number is an object. The number 1 is not a number as known by other languages, but a class instance of the fixnum object. And as an object, it has methods, of course.

1.odd? #calling a method of the number 1

But what, if we don’t call methods? For example:

1 + 2

Well, if you already worked with the info pane, you might have noticed, that Ruby puts the number 3 in there. Better said: It returns 3. And what returns something? Correct, a method. In fact we didn’t work with an operator (“+”), but with a method. The Ruby way of writing the above makes it instantly clear:

1.+ 2

We’re calling the method + of the fixnum class 1, passing the fixnum class 2 as an argument. There are no parentheses, because Ruby only needs them when calling in-place. Let’s do so, and you see what I mean:

1.+(2).* 2

Yes, you need to get used to it. But remember, I told you that Ruby is consequent. So, this is what you would write in other languages as (1 + 2) * 2
Don’t worry, there is also a way to write the equivalent of 1 + 2 * 2 (which results in 5, not 6). And that way is also a proof that even parentheses represent objects! Let’s additionally subtract 1 in the end. (1 + 2) * 2 – 1 would result in 5, while 1 + 2 * 2 – 1 results in 4. The last one in object form is:

1.+(2.* 2).- 1

A full stop/period is referencing a method as you know. There’s a period after the closing parenthesis. Confused? Here’s what’s going on. At first we call the addition method of 1, but the argument is calling the multiplication method of 2. So this method is executed first, and it returns an object (the number 4), which is now passed as an argument. The result is an object again (the number 5), and objects have methods. So we call the subtraction method of the resulting object, passing 1 as an argument. And there we are with the final result of the number 4. Parentheses represent objects, because whatever they enclose returns an object. Therefore we can use methods on expressions enclosed in parentheses.

(1 + 2).odd? #returns true, because the resulting object from the parentheses is 3

Control structures

Did I mention that Ruby is consequent? Even control structures act like objects! They return an object and can therefore be used like any other object:

a = 1
b = if a < 2 then 3 else 4 end

Even spanning several lines, they are still usable like any other object:

a = 1
b = case a
when 1
	3
when 2
	4
end

The nature of loops makes it impossible to use them like objects, but there are still ways to directly assign their results, for example:

a = 0
b = [a.upto(4) {a += 1}, a][1]

Real world examples

Following are some things I found on Flowstone forums. They use conventional syntax or semantic. I provide a more Ruby-like (and speed-optimized) alternative.

#not optimal
#variant 1
0.upto(a.length-1) do |i|
end
#variant 2
0.step(a.length-1,1) do |i|
end

#better
a.each_index do |i|
end
#horrible old syntax, hard to read
max = a[i] > max ? a[i] : max

#better
max = if a[i] > max then a[i] else max end

#best
max = [max, a[i]].max

#do the same for min
#if you iterate over the whole array, instead just use:
min = a.min
max = a.max
min, max = a.minmax

My conclusion is to look for any object methods before trying to use syntax from other languages. If you use Ruby really object oriented, you will have a clean, readable, maintainable and beautiful resulting code.

0 0 0 0 0
tulamide

About the author:

All kinds of script languages, Python, Ruby, Construct, Construct 2. Writing (if you understand german, have a look at 'Wortheim' via http://tulamide.tumblr.com/ ), electronic music, UI design. Too much for one life ;)

Tags:

4 Comments

  1. Exo
    Exo  - March 20, 2015 - 6:27 am

    Great article Tom! This is important stuff to know, especially that numbers are objects too.
    I am guilty of using the syntax in the examples given, I learnt these from the examples in Flowstone. It is a shame that the Ruby code in Flowstone is generally not the best example.

    I must say I am enjoying Ruby much more now than I am doing things more the “Ruby way”. This language is great for getting things running quickly and has methods for just about everything so we rarely have to write our own loops.

    • tulamide
      tulamide  - March 21, 2015 - 8:10 am

      You are so right in everything you said. I remember my first loop in Ruby:
      n = ary.length – 1
      for i in 0..n

      It couldn’t be more old-school xD

      I had more code examples, but then I thought it could be misinterpreted as showing somebody up, so I decided to just use what I found from the Flowstone examples.

  2. martinvicanek  - March 20, 2015 - 7:15 am

    Thanks, tulamide, your contributions are much appreciated. Your competence and enthusiasm for Ruby might help me to overcome my FORTRAN-spoiled programming approach. :o)

    • tulamide
      tulamide  - March 21, 2015 - 8:12 am

      Thank you so much! And, yes, if it helps getting you away from FORTRAN, I will continue xD

Add Comment Register



Leave a comment

You must be logged in to post a comment.

Back to Top