Articles / Why You Might Want to Try R…

Why You Might Want to Try Ruby

Ruby. Perhaps you've heard of it? "Oh, yeah, I think it's one of those new object oriented scripting languages", you say. I know a lot of you might be thinking "Not another new language! I'm perfectly happy with [COBOL|C|cshell|awk|Perl|...]; why does the world need another programming language?!", while a few others are thinking "Cool, a new language to explore".

Those of you in the former camp should ask yourselves this question: What if all programmers back in the days when COBOL ruled the mainframe had the same attitude? Fortran would still be an academic curiosity, and we might all be programming in COBOL at work, while C might not even exist yet. Not a pretty picture. That's why we need some folks around who are in the latter, early adopter camp. The purpose of this article is to persuade some early adopters to give Ruby a try (no hidden agendas here :).

Why should you try Ruby? Remember Maslow's hierarchy of human needs from that Psych 101 class you took way-back-when? At the bottom of the pyramid, there are things like food, water, and shelter. It progresses up to things like security, and finally, at the top, there's a category called "self-actualization", which basically means (my paraphrase) "fun stuff". No, you don't learn Ruby to secure food, shelter, and security (at least not yet); that's why you learn languages like C/C++, Java, and Perl. (Though after you learn Ruby, you'll certainly hope that you can start using it soon at work.) You learn Ruby, at this point, primarily because it's fun.

Ok, so what kind of language is Ruby, anyway?

Ruby is a "dynamically strongly typed", single-inheritance object oriented programming language. It's dynamically typed in that types are checked at runtime, and types of variables don't need to be declared. It's strongly typed in that if you try to use an object of a certain type in a way that the type doesn't understand, an exception (or error) will be raised. The term "object oriented" is applied to a lot of things these days. There's object oriented Perl, for example, but though you can do OO in Perl, it's not a pretty sight. In the early 90s, the creator of Ruby, Yukihiro Matsumoto (AKA "Matz") was looking for an object oriented scripting language which had the text processing capabilities of Perl. He looked at Python, but even it was not OO enough for his tastes, so he ended up creating Ruby. If SmallTalk dwells in the most OO region of ProgrammingLanguageLand (as many believe), then Ruby lives right next door.

Numbers, string literals, regular expressions... these are all objects in Ruby. Here are a few examples of this in Ruby code ("==>" means "results in"):

3.times { print " hey " } ==> " hey hey hey "
" this is a string ".length ==> 21
/^IF .. ^END/.type ==> Regexp

Ruby has a large number of built-in types, including Array, Hash, String, File, Thread, and Time. Each of these types or classes has a very complete set of methods which act on objects of that type. This lets you get more done with less code. For example, let's say you have a string with leading and trailing whitespace, and you want to get rid of them:

string = " this is a string "

You can apply the strip! method to it, like this:

string.strip! ==> "this is a string"

Methods which have a "!" at the end are destructive; they change the object they are applied to.

Now, let's capitalize our string:

string.capitalize! ==> "This is a string"

If you want to change "string" to "phrase", do this:

string.gsub!(/string/,"phrase")

And there are a lot more actions that can be performed on strings...

Even though Ruby's built-in classes have very complete sets of methods to act upon them, you're bound to find a need for some action that may not be built-in to a type, so Ruby allows you to extend its built-in types. For example, I wanted to rotate the contents of an Array. Ruby's Array class doesn't have a built-in rotate method, so I made my own and added it to the Array class:


class Array
  def rotate!
     self.unshift( self.pop)
     return self[0]
  end
end  

After that declaration, all objects of type Array in my program will respond to the rotate! method. This implies that classes in Ruby are not closed; you can always extend either built-in classes or classes you define. In fact, you can even do this at runtime, which makes Ruby a very dynamic language indeed.

As mentioned earlier, Ruby is a single inheritance OO language. Some might see the single inheritance part as a liability, but, in fact, Ruby allows for something called mixins. A mixin is a set of behaviors or functions defined within a module which can be included (mixed in) to a class. In practice, mixins tend to make up for the lack of multiple inheritance.

Perhaps the coolest feature of the Ruby language is the iterator. Iterators are methods that can invoke blocks of code. For example, all of the collection classes in Ruby implement the each method, which is an iterator that accepts a code block.


hobbits = ['frodo','sam', 'pippin']
hobbits.each { |name|
   puts "my name is: #{name}"
}

prints:

my name is frodo
my name is sam
my name is pippin

You can create your own iterators by using the yield statement:


def iterate(max)
   i = 0
   while i < max
      yield i
      i += 1
   end
end
iterate(10){|val| puts " val is: #{val}" }

prints:

val is: 0
...
val is: 10

Hopefully, these examples have illustrated Ruby's clean, consistent syntax. One of Matz's goals in designing Ruby is that it should follow the "principle of least surprise", and in my experience, it does tend to follow that maxim. There are many other cool features of Ruby (like GUI toolkits, Ruby's easy-to-use distributed object system (dRuby), Threads, etc.); I've just scratched the surface here to whet your appetite. You can find more information on Ruby at:

The newsgroup comp.lang.ruby is also quite informative and newbie friendly. Ruby is quite popular in Japan, the land of its beginnings, and it is growing in popularity in the West as well (I notice that there are 40 projects on freshmeat which are Ruby-related). There are currently two English language Ruby books, Programming Ruby: The Pragmatic Programmer's Guide by Dave Thomas and Andrew Hunt (you can find the full text of the book online at http://www.rubycentral.com/book/) and Ruby in a Nutshell by Matz himself. Three other Ruby books are planned for release early next year.

Go explore; have fun!

Recent comments

14 May 2004 13:07 Avatar brixen3

Re: What does "more OO" mean?

>
> [Ack. so far]
>
> > 2. Ruby has true open classes. Python
> > allows you to redefine existing classes;
> > but when you do, existing instances of
> > the redefined class do not reflect any
> > changes you made to the class. Only
> > objects created after the redefinition
> > pick up on the changes.
>
>
>
> That's definitely not true (following
> code tested
> on Jython 2.1):
>
>
> class MyClass:
> &nbsp;&nbsp;&nbsp;myAttrib = "one"
> &nbsp;&nbsp;&nbsp;def
> showMyAttrib(self):
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print
> 'here is: -%s-' % self.myAttrib
>
>
> def changeAClass(klasse):
> &nbsp;&nbsp;&nbsp;def aPrinter(self):
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print
> "once again -%s-" % self.newestAttrib
> &nbsp;&nbsp;&nbsp;def
> makeNewestAttrib(self):
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.newestAttrib
> = 'three'
> &nbsp;&nbsp;&nbsp;klasse.__dict__["makeNewestAttrib"]
> = makeNewestAttrib
> &nbsp;&nbsp;&nbsp;klasse.__dict__["printNewestAttrib"]
> = aPrinter
>
>
>
> myObject = MyClass()
> print myObject.myAttrib
> myObject.showMyAttrib()
> print "--- The Change ---"
> changeAClass(MyClass)
> myObject.makeNewestAttrib()
> print myObject.newestAttrib
> myObject.printNewestAttrib()
>
> Gives following output:
>
> one
> here is: -one-
> --- The Change ---
> three
> once again -three-
>
>
>
> > This can result in objects in the same program that
> > report the same type, but behave differently.
> > When a class is modified in Ruby, every object of
> > that class immediately exhibits the changed
> > behavior/interface.
>
>
> 1.) You see above, that Python does the
> same.

I may misunderstand, but I think the original author's point can be demonstrated as follows:


Python 2.3 (#1, Aug 19 2003, 15:54:06)

[GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> class Foo:

... def func(self):

... print 5

...

>>> f = Foo()

>>> class Foo:

... def func(self):

... print 9

...

>>> g = Foo()

>>> f.func()

5

>>> g.func()

9

>>> f.__class__

[class __main__.Foo at 0x4036492c]

>>> g.__class__

[class __main__.Foo at 0x4036495c]


whereas in Ruby (1.8.1):


irb(main):001:0> class Foo

irb(main):002:1> def func()

irb(main):003:2> print 5, "\n"

irb(main):004:2> end

irb(main):005:1> end

=> nil

irb(main):006:0> f = Foo.new

=> #[Foo:0x400cbcb8]

irb(main):007:0> f.func

5

=> nil

irb(main):008:0> class Foo

irb(main):009:1> def func()

irb(main):010:2> print 9, "\n"

irb(main):011:2> end

irb(main):012:1> end

=> nil

irb(main):013:0> g = Foo.new

=> #[Foo:0x400b0ecc]

irb(main):014:0> g.func

9

=> nil

irb(main):015:0> f.func

9

=> nil

irb(main):016:0> g.class

=> Foo

irb(main):017:0> f.class

=> Foo


So, I think the point was that, while in Ruby the class is always open, in Python an object of the previous definition of the class is not updated when the class is updated, as shown.

02 Sep 2003 03:01 Avatar vudmaska

Re: What does "more OO" mean?
Thanks a bunch for this article. I've been working with
a few scripting languages, weening myself from asp/
javascript, looking for a new server-side/language/
platform(not because i do no like javascript...M$). I'd
come to the conclusion Ruby was 'better' than
most(certainly php, probably python, and javascript
because is not well supported server-side), but i could
not have said
why as succinctly as you have. I'd mention, as a
differentiating factor, the inherent capabilites of
iterators with
scoping...for example, calling an iterating method on a
file and closing it magically at the end. Ruby rocks. It
does what you think it should.
Can't wait for it to mature/harden and i can get it on a
prod server.

Thanks!

18 Jun 2002 05:47 Avatar DetGermany

Re: What does "more OO" mean?

[Ack. so far]

> 2. Ruby has true open classes. Python
> allows you to redefine existing classes;
> but when you do, existing instances of
> the redefined class do not reflect any
> changes you made to the class. Only
> objects created after the redefinition
> pick up on the changes.


That's definitely not true (following code tested
on Jython 2.1):

class MyClass:

&nbsp;&nbsp;&nbsp;myAttrib = "one"

&nbsp;&nbsp;&nbsp;def showMyAttrib(self):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'here is: -%s-' % self.myAttrib



def changeAClass(klasse):

&nbsp;&nbsp;&nbsp;def aPrinter(self):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print "once again -%s-" % self.newestAttrib

&nbsp;&nbsp;&nbsp;def makeNewestAttrib(self):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.newestAttrib = 'three'

&nbsp;&nbsp;&nbsp;klasse.__dict__["makeNewestAttrib"] = makeNewestAttrib

&nbsp;&nbsp;&nbsp;klasse.__dict__["printNewestAttrib"] = aPrinter


myObject = MyClass()

print myObject.myAttrib

myObject.showMyAttrib()

print "--- The Change ---"

changeAClass(MyClass)

myObject.makeNewestAttrib()

print myObject.newestAttrib

myObject.printNewestAttrib()

Gives following output:

one

here is: -one-

--- The Change ---

three

once again -three-

%This can result
> in objects in the same program that
> report the same type, but behave
> differently. When a class is modified
> in Ruby, every object of that class
> immediately exhibits the changed
> behavior/interface.

1.) You see above, that Python does the same.


2.) Ruby has been praised for the ability to
do exactly what you find fault:

Have the possibility to change a dedicated _object_
with object.extend without changing the whole class.

So what?

> 3. 'self' as a keyword. In Python, you
> must put 'self' in the argument
> declaration of every method;

which allows the class extension you see above.

> In effect, Python forces
> the programmer to help the interpreter
> to remember what object the method has
> been called on.

Yes, its annoying, especially if you work with
different languages in parallel. You everytime forget
to write this to the signature.

> In Ruby, 'self' is a
> keyword; in a method body, 'self' always
> refers to the object that the method was
> called from. No need to define 'self'
> in the argument list.


18 Jun 2002 05:07 Avatar DetGermany

Re: Iterators ain't nothing new,

>
> % well, if your first argument is a
> code
> % block, then the sub keyword is
> optional.
> % the parens are optional anyway, so
> you
> % could really write it like this:
> %
> % iterate { CODE } @list;
> %
> % which makes it much more along the
> % lines of
> %
> % map {CODE} @list;
> % grep {CODE} @list;
> % sort {CODE} @list;
> %
> % functional programming in perl
>
>
> Yea, well - the nice thing about Perl,
> is that it doesn't force you into using
> a single programming technique or
> paradigm. although basicly if a
> procedural language, you can write
> functional perl, OO perl, or plain old
> a-la basic flat perl (with gotos
> sprinkled for good measure ;-)


Again this is nothing special. Python explicitly does the same, as you can use it procedural and it has features for functional programming, especially the map, reduce and filter functions, and a strong list type.

OTOH: You can use Ruby in a procedural way too, as you can define functions without classes (although they will become methods of object ... what does it matter?) , and have statements on file level without surrounding methods (even like in a procedural script).

You can think of some Ruby features from a functional point of view, e.g. when passing around Procs, or using the &quot;anonymous function&quot; called 'block'...

No outstanding features of perl, these.

19 Mar 2002 13:40 Avatar Guss

Re: Iterators ain't nothing new,

> well, if your first argument is a code
> block, then the sub keyword is optional.
> the parens are optional anyway, so you
> could really write it like this:
>
> iterate { CODE } @list;
>
> which makes it much more along the
> lines of
>
> map {CODE} @list;
> grep {CODE} @list;
> sort {CODE} @list;
>
> functional programming in perl


Yea, well - the nice thing about Perl, is that it doesn't force you into using a single programming technique or paradigm. although basicly if a procedural language, you can write functional perl, OO perl, or plain old a-la basic flat perl (with gotos sprinkled for good measure ;-)

Screenshot

Project Spotlight

Kigo Video Converter Ultimate for Mac

A tool for converting and editing videos.

Screenshot

Project Spotlight

Kid3

An efficient tagger for MP3, Ogg/Vorbis, and FLAC files.