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!
Access to JIRA, Crucible, and Bamboo from Eclipse using Mylyn.
The expected (probably) Python 2.2 comment
Ruby is a fine language, I have tried it.
However I would really recommend Python 2.2 [http://www.python.org/2.2/],
why?
Well, mainly because of the wealth of
bundled modules and classes. Most tasks can be
coded in a few minutes without thought!
Not neccisarily a good thing I beleive, but it does
allow rapid prototyping of the four in the morning
"hey I wonder if that will work" syndrome
allowing me to get some sleep.
The crossplatform consistancey of supplied
classes is also very good. My only niggle with the
old versions was the inbalance between types and
classes, this is now fixed in version 2.2.
Also, for colleagues, the code (although
probably not mine) is readable, almost like a object
orientated version of pseudocode (see caveat in
last brackets). Although maybe understanding of
classes is essential for quick pickup, but if you've
coded C++ it's very easy to pickup.
Da da, da da da Da Da Da, da da Da da Da
Daaa.
The nicest language I've ever used.
I try not to be terribly pedantic when it comes to languages, and I'm happy using several in my professional life, but Ruby is far and away the nicest language I've ever used. I love Perl, but I've always wanted better OO support. Python is nice, but I think it's obvious that OO isn't Van Rossum's preferred paradigm (which is fine). Java is a great language with great OO facilities (like abstract classes and interfaces), but the syntax is verbose and it lacks the text-manipulation power and ease-of-use of either Perl or Python. C++ is, well, C++.
I still use all these other languages, but Ruby has definitely become my favorite. The OO is outstanding (everything is an object; there are no exceptions. period), and the syntax is incredibly clean. Once you're introduced to blocks and iterators I guarantee you'll become an addict. I haven't seen any benches, but it seems palpably faster than Python. All in all, it feels like the language in which all the things that annoy me about the other languages (sometimes minor things) have been done away with.
Someone characterized Ruby as the first "post-scripting" language. I absolutely agree. I wouldn't hesitate to write a very large system in it, and I definitely wouldn't hesitate to recommend it to anyone.
My take on Ruby
I recently learned Ruby and I really like it. I can't speak to Python (although there is a Ruby faq about it (http://www.rubycentral.com/faq/rubyfaq-2.html)), but I do have a reasonable amount of Perl experience.
I find that Ruby works just as well as Perl as a "glue" language because Ruby borrows a lot of the things that make Perl so well suited to that role (e.g. regexps, the backtick operator, pipes, easy text processing). You also have added to that Ruby iterators, among other things. This is a tremendously powerful and practical feature. Once you get used to it, you will really find yourself missing it in other languages. There is also Ruby's exception handling system, which can be very useful for this type of thing. Perl's main advantage over Ruby in the glue language arena is its huge number of add-on modules. Ruby is getting better in this area, but you still won't find Ruby analogues for Perl's more esoteric modules.
Where Ruby really shines is in building more complex projects where OO design strategies become useful. Ruby's OO features are simple, elegant, extremely powerful, and much easier to understand than Perl's for non-wizards. It really does seem more akin to Smalltalk than anything else I've used (conceptually, if not syntactically), but not as "weird".
Anyway, just wanted to share the impressions I drew from my experience with Ruby. It's an interesting language and I definitely recommend checking it out.
Revisionist history strikes again
I'm sure Ruby is great. Next time though check
your history a little better. Fortran preceded
Cobol. We'ld all be programming in Fortran
rather then Cobol if people didn't try new things.
Here is a URL. (http://www.princeton.edu/~ferguson/adw/programming_languages.shtml)
I have secured food and shelter...
I work for a company that allowed me to rewrite one of our existing Windows/Visual Foxpro/COM systems using Ruby, and development has been rapid and clean. The community is extremely helpful, there are excellent books available, and the syntax is familiar enough that someone from a Java or Perl background can pick it up quickly. Ruby has given us an easy way to express our UML diagrams in code. Wrapping C with it is very easy, and this has allowed me to add features to wrappers around upstream code without difficulty.
One double-edged sword is the dynamic typing, which lets you do amazing things, but at the price of any useful compile-time checking. We compensate for this by using pair programming and test-first development. Test suites and other tools for eXtreme Programming and friends seem important to the community and there are a few testing frameworks available.
I wouldn't hesitate to use Ruby on our next project.
Error?
In your article you say:
3.times { print " hey " } ==> " hey hey hey "
Surely the correct result would be " hey hey hey "?
irb -> two nits...
I'm a big ruby user (ruby-dbi + postgres is a thing of beauty) and by far and away, amongst the numberous cool thing that have stopped me from using other languages if at all possible, is irb. Here's a quick session that shows some of it's usefulness and also points out a small nit (same applies to the string.capitalize! example):
> irb
irb(main):001:0> string = " this is a string "
" this is a string "
main):002:0> string.strip
"this is a string"
irb(main):003:0> string
" this is a string "
irb(main):004:0> string.strip!
"this is a string"
irb(main):005:0> string
"this is a string"
irb(main):006:0> puts string
this is a string
nil
irb(main):007:0> p string
"this is a string"
nil
irb(irb(main):008:0> exit
>
After 5 years of working with Perl, programming is fun again. -sc
PHP -> eRuby
And for those of you who are PHP fans, check out eRuby. Ruby works extremely well as an embedded language like PHP. One of the big wins with eRuby over PHP is that when you want to add a module to Ruby, you don't have to recompile the interpreter: it's just a module that you require from your script (like Perl).
Heh, who's old...
Ok, so I personally do not think that COBOL is anything but a very good thing. Modern COBOL is very nice. But Ruby is so sweet. It's got the best mix of perl and smalltalk that I can't help loving it.
Re: Error?
> In your article you say:
>
> 3.times { print " hey " } ==> " hey
> hey hey "
>
> Surely the correct result would be "
> hey hey hey "?
People get the general idea, you don't need to troll the author of the article; he simply wants to inform you of a great programming language. What harm does it do you to overlook a simple mistake?
Alternative Programming Language
I frequent Freshmeat and I never found a need to post anything till now. I enjoy learning about new things in the development scene and Ruby struck me as one of those things, however, this happened a couple of months back.
I heard the suggestion on an Alternative Tech site
www.rantitraveit.com
http://www.rantitraveit.com/cgi-bin/ikonboard/topic.cgi?forum=8&topic=1
It's good to see Freshmeat start to talk about it now though
Re: Error?
>
> % In your article you say:
> %
> % 3.times { print " hey " } ==> "
> hey
> % hey hey "
> %
> % Surely the correct result would be
> "
> % hey hey hey
> "?
>
>
> People get the general idea, you don't
> need to troll the author of the article;
> he simply wants to inform you of a great
> programming language. What harm does it
> do you to overlook a simple mistake?
>
>
I'm sad that you think of me as a troll :( I'm merely pointing out a simple mistake in his post, no malice is intended towards ruby or the author.
Re: Error?
>
> %
> % % In your article you say:
> % %
> % % 3.times { print " hey " } ==>
> "
> % hey
> % % hey hey "
> % %
> % % Surely the correct result would
> be
> % "
> % %
> hey hey hey
> % "?
> %
> %
> % People get the general idea, you
> don't
> % need to troll the author of the
> article;
> % he simply wants to inform you of a
> great
> % programming language. What harm does
> it
> % do you to overlook a simple
> mistake?
> %
> %
>
>
> I'm sad that you think of me as a
> troll :( I'm merely pointing out a
> simple mistake in his post, no malice is
> intended towards ruby or the author.
>
To carry on the trend of long and meaningful posts:
Oops.
Experiences from integrating Ruby with Siag Office
Siag Office 3.5.0 (just released) includes some preliminary support for the Ruby language. I didn't have any previous experience from Ruby, but plenty from interfacing with other interpreter libraries. It was fairly painless.
The interface is *very* similar to Scheme interpreters I've worked with, especially Guile. I don't know if that is by design, by coincidence or because they are actually related in some way.
There was one showstopper problem: Ruby has an internal header file called regex.h, which is for some reason installed into the same directory as all other Ruby headers. Creating nonstandard headers with the same name as standard Posix headers is a Really Bad Idea. I solved it for myself by renaming the file to something else and hacking the Ruby source accordingly.
There is also the problem with esp. macros called generic names like TYPE or VALUE, which is bound to cause collisions with other things. But that didn't happen in this case.
Re: PHP -> eRuby
> One of the big wins with eRuby over PHP
> is that when you want to add a module to
> Ruby, you don't have to recompile the
> interpreter: it's just a module that you
> require from your script (like Perl).
Well, you dont need to recompile php.
just use dl()
for loading a module direct from script:
http://www.php.net/manual/en/function.dl.php
regards,
Peter Petermann
What does "more OO" mean?
I've noticed that few promoters of Ruby have much to say about why Ruby is better than Python, except that it's "more OO". But I haven't seen what these "more OO" features are, that aren't available in Python 2.2.
For example, iterators and generators. Your example:
def iterate(max)
i = 0
while i < max
yield i
i += 1
end
end
iterate(10){|val| puts " val is: #{val}" }
reads like this in Python 2.2:
from __future__ import generators
def iterate(max):
i = 0
while i < max:
yield i
i += 1
for val in iterate(10):
print "val is:", val
Same feature, but a bit more readable. And a whole lot more things built in. Also, as of 2.2 you can subclass Python built-ins like integers, strings, etc., if you need or want to, as well as any extension type you define in C.
I really am curious to know what these other "OO" features are.
Iterators ain't nothing new,
And perl implements something much more useful, and to my taste - better designed : the anonymous subroutine or code block. for example, take this piece of code (I could have written it better, I know - but it gets the job done) :
@list = (1,2,3,4);
iterate (sub { print "number: $_[0]\n"; },@list);
sub iterate {
my ($code,@input) = @_;
foreach $num (@input) {
&$code($num);
}
}
there is no "magic" yield method, no "magic" code blocks apended to a function call - you just pass a code block as a parameter to a term or a subroutine. you can also pass code references if you like. if you've ever used the sort term in perl, then you've used anonymouse code blocks.
Iterators in Perl are even more fun when using closures :
@list = (1,2,3,4);
$itr = make_itr(@list);
while (defined($next = &$itr)) {
print "number $next\n";
}
sub make_itr {
my @data_range = @_;
my $cur = 0;
return sub {
return undef unless ($cur < @data_range);
return $data_range[$cur++];
};
}
hmm.. comes to think of it, Perl has one more ace against Ruby - Perl developers have better job security ;-)
Re: Iterators ain't nothing new,
> And perl implements something much more
> useful, and to my taste - better
> designed : the anonymous subroutine or
> code block.
Ruby has those too. They're called procs.
They are also closures.
> there is no "magic" yield method, no
> "magic" code blocks apended to a
> function call - you just pass a code
> block as a parameter to a term or a
> subroutine. you can also pass code
> references if you like.
I suspect that I could do, in Ruby (without using
yield), exactly what you've done in Perl if I used
procs. But yield makes it so much easier and more
readable. Yes, I came from Perl-land as well and
initially I didn't see why I needed 'yield'
either, but look a bit more closely and perhaps
actually play with it and you'll come to really
apreciate it.
(BTW: yield is being added to Perl6)
%starquote%
> hmm.. comes to think of it, Perl has
> one more ace against Ruby - Perl
> developers have better job security ;-)
Yeah, they have to keep the perl developer around
because nobody else in the oragnization (including
other Perl programmers) can figure out what the
program was supposed to do. ;-)
pt
Re: What does "more OO" mean?
> I've noticed that few promoters of Ruby
> have much to say about why Ruby is
> better than Python, except that it's
> "more OO". But I haven't seen what
> these "more OO" features are, that
> aren't available in Python 2.2.
>
> For example, iterators and generators.
> Your example:
>
>
> def iterate(max)
> i = 0
> while i < max
%
> yield
> i
> i
> += 1
> end
> end
>
> iterate(10){|val| puts " val is:
> #{val}" }
>
>
> reads like this in Python 2.2:
>
>
> from __future__ import generators
>
> def iterate(max):
> i = 0
> while i < max:
%
> yield
> i
> i
> += 1
>
> for val in iterate(10):
> print "val is:",
> val
>
>
>
> Same feature, but a bit more readable.
> And a whole lot more things built in.
> Also, as of 2.2 you can subclass Python
> built-ins like integers, strings, etc.,
> if you need or want to, as well as any
> extension type you define in C.
>
> I really am curious to know what these
> other "OO" features are.
Here are some examples for you:
"Hello".length
5.times { print "hey" }
Where .length is a method of class String and .times is a method of class Integer.
Re: What does "more OO" mean?
>
> %
> % I really am curious to know what
> these
> % other "OO" features are.
>
>
> Here are some examples for you:
>
> "Hello".length
>
> 5.times { print "hey" }
>
> Where .length is a method of class
> String and .times is a method of class
> Integer.
So how is that "more OO" than the methods available on strings and integers in Python, except in which methods they have and how they're named? That doesn't strike me as being "more", just "different". And that you didn't give any examples other than those mentioned in the article, seems to suggest that there's not really a whole lot else different, which was the point of my question.
Re: What does "more OO" mean?
>
> %
> % %
> % % I really am curious to know what
> % these
> % % other "OO" features are.
> %
> %
> % Here are some examples for you:
> %
> % "Hello".length
> %
> % 5.times { print "hey" }
> %
> % Where .length is a method of class
> % String and .times is a method of
> class
> % Integer.
>
>
> So how is that "more OO"
> than the methods available on strings
> and integers in Python, except in which
> methods they have and how they're named?
> That doesn't strike me as being
> "more", just
> "different". And that you
> didn't give any examples other than
> those mentioned in the article, seems to
> suggest that there's not really a whole
> lot else different, which was the point
> of my question.
>
In Ruby, everything is an object. That's the difference.
Python:
>>> "Hello".count
<built-in method count of string object at 008A1D80>
Ruby:
irb(main):001:0> "Hello".length
5
Every class is an object, 'true' is an object, 'false' is an object, even 'nil' is an object.
Re: What does "more OO" mean?
>
> In Ruby, everything is an object.
> That's the difference.
>
> Python:
> >>> "Hello".count
> <built-in method count of string
> object at 008A1D80>
>
> Ruby:
> irb(main):001:0>
> "Hello".length
> 5
>
> Every class is an object, 'true' is an
> object, 'false' is an object, even 'nil'
> is an object.
I don't get you. All those things are objects in Python, also. Note, by the way, that "Hello".count("l") returns 2, and "Hello".__len__() returns 5. I'm not sure what you're trying to say here. Everything in Python is an object, including functions, code, modules, classes, instances, types, metaclasses/metatypes, methods, iterators, generators... They're the same all the way down to sharing the same C header structure. And that's been the case for every version of Python I've ever worked with.
In Python versions prior to 2.2, extending types developed in C couldn't be done without either coding in C or the use of the ExtensionClasses add-on. But that didn't change things being objects - there were simply limits to which types could be extended without C code being involved.
I've dug through the Ruby FAQ looking for a meaningful Ruby-Python comparison, and the only such information that I saw was written by a Python programmer who mostly listed the differences which went away as of Python 2.2. I did notice that Ruby offers continuations, however, and a few other little odds and ends that are difficult in Python without special extensions (such as the Stackless Python patch).
But nobody seems to mention these features in comparison situations, instead repeating the "everything's an object" mumbo jumbo which is not actually a difference from Python. If folks are serious about having Python programmers check out Ruby, it would be good for them to mention some actual feature differences.
Re: What does "more OO" mean?
>
> %
> % In Ruby, everything is an object.
> % That's the difference.
> %
> % Python:
> % >>>
> "Hello".count
> % <built-in method count of
> string
> % object at 008A1D80>
> %
> % Ruby:
> % irb(main):001:0>
> % "Hello".length
> % 5
> %
> % Every class is an object, 'true' is
> an
> % object, 'false' is an object, even
> 'nil'
> % is an object.
>
>
> I don't get you. All those things are
> objects in Python, also. Note, by the
> way, that
> "Hello".count("l")
> returns 2, and
> "Hello".__len__() returns 5.
> I'm not sure what you're trying to say
> here. Everything in Python is an
> object, including functions, code,
> modules, classes, instances, types,
> metaclasses/metatypes, methods,
> iterators, generators... They're the
> same all the way down to sharing the
> same C header structure. And that's
> been the case for every version of
> Python I've ever worked with.
>
> In Python versions prior to 2.2,
> extending types developed in C couldn't
> be done without either coding in C or
> the use of the ExtensionClasses add-on.
> But that didn't change things being
> objects - there were simply limits to
> which types could be extended without C
> code being involved.
>
> I've dug through the Ruby FAQ looking
> for a meaningful Ruby-Python comparison,
> and the only such information that I saw
> was written by a Python programmer who
> mostly listed the differences which went
> away as of Python 2.2. I did notice
> that Ruby offers continuations, however,
> and a few other little odds and ends
> that are difficult in Python without
> special extensions (such as the
> Stackless Python patch).
>
> But nobody seems to mention these
> features in comparison situations,
> instead repeating the "everything's
> an object" mumbo jumbo which is not
> actually a difference from Python. If
> folks are serious about having Python
> programmers check out Ruby, it would be
> good for them to mention some actual
> feature differences.
Ok, after poking around a bit i have to admit it looks better than i thought, they've somehow gotten most of the language to behave mostly like real Python objects.
* Getters and Setters
Automatically generated getters/setters for class attributes, which can later be custom implemented without affecting the surrounding code.
* Attributes are private
The only way to access to the internals of an object is through getters and setters, see above.
* Messagebased instead of procedural
No need for (self, ....) method declarations
* Module mixins
A compromise between multiple interitance and Java's interfaces.
* Default method
A default method can be declared to handle all messages that doesn't have a corresponding method.
Makes it easier to implement many design patterns, like for example the Proxy pattern.
* Reflection
It's E-A-S-Y to get a list of methods or attributes for a class/object.
It's E-A-S-Y to declare new functions and new attributes at runtime.
* Ability to extend single objects
Objects can be further extended.
That is, you can make different objects of the same class behave differently.
All in all ruby is ObjectOriented in a cleaner more consistent way than Python.
We're obviously seing this from different perspectives. As I see it, I don't gain anything from you checking out Ruby. In fact, the only one gaining anything would be YOU. I'm doing you a favour ;)
A Suggested Cure for the Missing Ruby Module Problem
> Ruby is a fine language, I have tried
> it.
> However I would really recommend
> Python 2.2 [
%
> href=http://www.python.org/2.2/>http://www.python.org/2.2/],
> why?
> Well, mainly because of the wealth of
> bundled modules and classes.
[...snip...]
If you feel Ruby is missing some of the modules and class library support available in Perl and Python, I would ask you to consider the relative ages of these fine languages. As is self-evident from a cursory perusal of the Library Reference, at http://www.rubycentral.com/ref/index.html, and the Ruby Application Archive (RAA) at http://www.ruby-lang.org/en/raa.html, volunteers have added a *huge* amount of functionality to Ruby in a *very* short time.
My humble suggestion: Ruby is fully Open Source, with a great and friendly user community. Feel free to contribute any modules you and your chosen army of coding fiends and friends believe are needed. Your help would be most welcome!
Grepninja -- (who appreciates and uses *all* of the aforementioned languages *plus* Squeak SmallTalk, Java, and C# and finds Ruby the most SmallTalk-comparable language he has seen outside of a SmallTalk Image and it even has full block closures thrown in for free -- Ruby is immensely cool!)
Re: What does "more OO" mean?
I learned Python and Ruby at about the same time, and I've spent some time comparing their OO-ness. I'll say right from the start that I *do* believe that Ruby os "more OO" than Python, but I hope to give some fairly plausable reasons for that statement.
Often, in comparisons of Ruby and Python, the statement is made that "Python 2.2 now has iterators and generators and subclassable built-ins". This is true. Does this mean that Python and Ruby are now equivalent? I would say no.
In many ways Ruby's OO nature is what Python has been striving towards for years. Only recently have iterators and generators been added to Python. Only recently has the type/class sytem been unified. In Ruby, those features have been incorporated since day one. This may seem like an academic point; after all, Python has those features /now/. Here's why it isn't: because iterators have always been in Ruby, each built-in Ruby class has a rich set of methods which exploit the power of iterators. With arrays, for instance, you can apply an arbitrary block of code to every element with each(); you can collect the result of applying a block to every element with collect(); delete every element for which the block matches with delete_if(); sort using an arbitrary code block; and other operations. Every other built-in type has a large set of opertations that exploit iterators to the fullest. Python provides iterators; but the built-in classes do not (to my knowledge) lend themselves to iterative operations out-of-box. In addition, the vast amount of libraries available for Python do not yet have pervasive support for iterators.
In a similar vein, built-in objects in python simply don't have as many methods available as Ruby objects. Python's built-in types cause Python's procedural heritage to show through. Much old code uses the old string.method("mystring") functions, making it hard for the beginner to know whether to use the string.* functions or the built-in string methods. Worse, it is hard for the beginner to predict whether a particular operation will be implemented as a free function or as a method. For example, to find out if the string 'my_str' is all alphabetic, I call my_str.isalpha; but if I want to know how long it is I must call len(my_str). In Ruby, there would never be any ambiguity - any built-in operation on a string is callable as a method of the string. Even worse is the inconsistency between tuples and lists. Despite tuples being (to all intents and purposes) the equivalent of a constant list, tuples have no methods, whereas lists have many. There is no apparent reason for this inconsistency.
Thus, while Python provides many of the same features as Ruby, because they were added so late in the game, it does not provide them in anything like the pervasive way that Ruby does.
On to other areas of comparison...
1. Ruby has no free functions. Like smalltalk, every function is either a class method or an object method. Even when you define a function outside of any class, you're actually defining a class method of the class Object. Not that this is inherently "better"; but it is more purely OO, according to academic definitions of OO.
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. 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.
3. 'self' as a keyword. In Python, you must put 'self' in the argument declaration of every method; but you must remember to pretend that argument doesn't exist when calling the method. Many Pythoneers have praised the explicitness of having to define 'self'; but the Python FAQ makes it quite clear that the only reason for this misfeature is that when OO was being added to Python, this was simply the easiest way to hack it in. In effect, Python forces the programmer to help the interpreter to remember what object the method has been called on. 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.
Re: Iterators ain't nothing new,
% @list = (1,2,3,4);
> iterate (sub { print "number:
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
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 ;-)
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 "anonymous function" called 'block'...
No outstanding features of perl, these.
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:
myAttrib = "one"
def showMyAttrib(self):
print 'here is: -%s-' % self.myAttrib
def changeAClass(klasse):
def aPrinter(self):
print "once again -%s-" % self.newestAttrib
def makeNewestAttrib(self):
self.newestAttrib = 'three'
klasse.__dict__["makeNewestAttrib"] = makeNewestAttrib
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.
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!
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:
> myAttrib = "one"
> def
> showMyAttrib(self):
> print
> 'here is: -%s-' % self.myAttrib
>
>
> def changeAClass(klasse):
> def aPrinter(self):
> print
> "once again -%s-" % self.newestAttrib
> def
> makeNewestAttrib(self):
> self.newestAttrib
> = 'three'
> klasse.__dict__["makeNewestAttrib"]
> = makeNewestAttrib
> 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.