Chad Perrin: SOB

14 June 2007

casually profound statements about Ruby

Filed under: Geek — apotheon @ 09:05

Shannon -jj Behrens offers some commentary about Ruby: A Python Programmer’s Perspective. It’s really just a collection of brief statements that point out the differences, with occasional references to Java and Perl for added context. I found that several of the statements made about differences between languages really served to highlight profound differences in language design philosophy. The following will focus on differences in the languages, not in the communities (though of course the two are related).

Here are a few that caught my attention, with some hints to what they mean in a grander sense than the statement itself makes clear:

Ruby is like Perl in that the last value of a function is its implicit return value. In Python, if there isn’t an explicit return statement, the return value is implicitly None.

Instance variables are never directly accessible outside the class in Ruby, unlike in Python or even Java.
Hint: Java and Python violate protection.

Ruby has protected and private members, which Python and Perl purposely chose to leave out. A private member in Ruby is even more private that a private member in Java. If you have two instances of the same class, in Java one instance can access the other instance’s private members, but that’s not true in Ruby.
Hint: Again with the protection violation.

Ruby uses modules as mixins instead of using multiple inheritance
Hint: There’s a reason I cut the sentence short three words early.

Ruby has “%w { foo bar bat }”, which is like Perl’s “q( foo bar bat )”. Python doesn’t have a construct for this, but you can use “‘foo bar bat’.split()”.
Hint: list processing (Note: Actually, its qw in Perl, not q — and neither is restricted to the specific delimiter indicated.)

In Python, there’s a much stronger emphasis on passing functions. I’m sure that it’s possible in Ruby, but it’s more natural to pass a block instead.

In Ruby, a failed lookup in a hash returns a default value, which is usually nil. You can set a different default if you want. Python will raise an exception if you try to access a key that doesn’t exist.
Note: The rest of this short paragraph indicates that this gap has been closed, but I felt it was worth contemplating the reason for Ruby’s behavior rather than concentrating on the fact that Python 2.5 adopts it.

In Ruby, you say “(hash[key] ||= []) << value”, whereas in Python, you say “hash.setdefault(key, []).append(value).”
Hint: defaults vs. edge-case coverage

In Python, it’s “len(obj)” (i.e. len is a generic function). In Ruby, it’s “obj.length” (i.e. polymorphism is used). This difference seems to happen a lot.
Hint: function vs. method

Ruby will let you assign a new value to a variable defined outside your scope [. . .] This was not previously possible in Python without using a workaround. However, Python is gaining this feature with the use of a keyword similar to the “global” keyword.
Hint: lexical vs. local scope

Coming at it from a different angle, in Java, you use explicit variable declarations to assign scope. This is true too in Perl when you use “my”. In Python, an assignment automatically sets scope. Hence, you can shadow variables in Java, Python, and Perl. Ruby tries really hard to avoid shadowing. Hence, whoever assigns to the variable first sets the scope.
Hint: This is related to the last comment — and good Perl practice has evolved to favor my() for lexical scope as the “should be default” choice.

Ruby has an === operator and case statements. This feature is a lot closer to the match feature in ML languages than anything in Python

In Ruby, only false and nil are considered as false in a Boolean expression. In particular, 0 (zero), “” or ” (empty string), [] (empty array), and {} (empty hash) are all considered as true.

In Python, 0, “”, ”, [], and {} are all considered False.

hint: variable value testing

In Ruby, if s is a string, you may write “s += ‘a'” or “s << ‘a'”. The first creates a new object. The second modifies s. If you modify s, that may “surprise” other pieces of code that also have a reference to s.
hint: encouraging vs. enforcing

In my opinion, they’re both great languages.
Note: I tend to think so, too. I definitely have my preference, though.

(PS: The webhost for this domain is pissing me off. It’s been broken for a while, making it difficult to post this.)

All original content Copyright Chad Perrin: Distributed under the terms of the Open Works License