

Some Mental Traps in Learning Ruby - mdemare
http://talklikeaduck.denhaven2.com/articles/2007/10/17/you-cant-judge-a-book-some-mental-traps-in-learning-ruby

======
timr
The most insightful text on the linked page is the first (currently only)
comment: this is unnecessary and confusing.

In fact, this is one of the "features" of Ruby that I hate -- it's frequently
difficult to know what a particular piece of code _does_ , because the Ruby
community's golly-gee fascination with interfaces and dynamic mixins tends to
lead to inconsistent behavior in different contexts.

The idea of separating interface and implementation is not new. Even us
crusty, abused C++ programmers can override the bracket operator; we just
happen to believe that overriding that operator in a way that leads to
unexpected behaviour for _particular subscript values_ is a Bad Idea.

The principle of least surprise is an important one in programming; I wish
that more people would obey it as a law.

~~~
mdemare
In Ruby, the subscript operator is just another method name. There's no
essential difference between an operator and a 'normal' method like to_s.

To know which method is called, you need to know the class of the receiver and
the method name - together they determine unambiguously which method is
called, and hence there is no surprise.

The only surprises occur when the programmer is mistaken about the type of an
object - those are the risks of dynamically typed languages.

~~~
timr
You've missed my point.

I understand that [] is a method in Ruby. In fact, operator[] is also a method
name in C++, and can be overloaded, overridden, etc. Ruby did not invent these
features. Likewise, in C++, the type of an object and the method name invoked
determine unambiguously the method that is called.

The difference -- and this is critical -- is that in the C++ community, there
is a strong bias _against_ syntactical games that make code behave
inconsistently. Having operator[] behave differently for different subscripts
would be a mortal sin in C++ design (not to mention that the type system would
probably punish you for it).

We can debate the relative merits of strong/weak typing, but the principle of
least surprise is a good one, and should be respected, regardless of what a
language may allow you to do (cf. Perl).

~~~
mdemare
First, of course the principle of least surprise is good, but it doesn't apply
here. No experienced Ruby programmer would look at 'a[0]' and think - oh, an
index into an array. They know that it could mean many things, depending on
the receiver, not the subscript value.

Also in Ruby there _is no overloading_. Overloading means that a different
method is chosen depending on the types of the arguments. That means that in
C++, it is _not_ true that "the type of an object and the method name invoked
determine unambiguously the method that is called".

In practise there is also little overriding - there seems to be no need. In
C++ there is a lot more, and because of multiple inheritance, things can get
confusing. (Overriding and overloading are two ways in which OO-languages
violate the principle of least surprise).

This means that the reasons why using operator overloading is bad in C++ don't
(automatically) apply to Ruby.

~~~
timr
I'm going to ignore your more pedantic points (e.g. method "signature" vs.
method "name", and the silly notion of "overloading" in a dynamically typed
language), and focus right on the meat of the argument:

Every "experienced Ruby programmer" may well come to understand that standard
expressions fail to mean standard things when used in Ruby; that doesn't make
it a good idiom. The problem here _isn't_ that the bracket operator fails to
reference into an array -- it's that the bracket operator might _behave
inconsistently_ for certain subscript values.

The STL map class is a perfect analogue: rather than implement an operator[]
than could fail in certain contexts, the C++ standard demands that
map::operator[] must _always_ return an object. This is consistent behavior.
Allowing operator[] to fail for subscript N-1 when it works for N? That's
inconsistent (and confusing), but apparently, it's the Ruby Way.

------
toisanji
DataMapper, an ActiveRecord replacement where I am one of the coders,uses the
same Person[1] syntax. Check it out sometime: <http://datamapper.org/>

~~~
jamesbritt
It's been part of Og for a while, perhaps from the beginning.

There seems to be some Ruby communal understanding that the use of [x] should
follow Array-ish behavior, but when used with a class constant it's apparent
that this is not simply an array, and that some other sort of indexing is
going on.

