Ruby stupidities

The title is intentionally (but semiseriously) contentious, but I’m not
trying to say that Ruby is a bad language–I’m using it, right :slight_smile: ?
However, any language has its unfortunate share of bad APIs, design
decisions, etc., and Ruby is no exception. I’ve stumbled across a few,
and thought it might be useful to start up a thread discussing what
people view as Ruby’s stupidities. Why? Because it’s a lot less painful
to find out about them by reading them than be tracking obscure errors
in one’s code.

In order to keep this on a not-completely-shouting-match level, I think
it’s fair to give a reason something you mention as a Ruby Stupidity is
in fact stupid. For example, it violates common sense, it causes more
trouble than it’s worth, etc. etc., and to discuss what a better way of
implementing such a feature might be.

Having said that, here’s my first entry. I think it’s utterly stupid
(can you tell I just wasted some time tracking this down?) that

"abc"[0] == "a"

is false. Why doesn’t that work? Because, with a single index, the array
access operator on a string returns, not the character at the given
position, but the character code of the character at that position.

And why is that stupid?
1) It’s inconsistent even in Ruby’s own String API; all other index
operations (at least as shown in the standard rdoc) give strings or nil.
2) It’s unusual compared to most other scripting languages, meaning
it makes Ruby less approachable.
3) There seems to be absolutely no reason to do things this way;
providing a ‘char_code’ string method would result in clearer programs,
and it’s not like converting a character to a char code is such a common
operation that it’s necessary to save a few keystrokes at the cost of
unclear code.

Here’s hoping someone out there avoids this mistake after reading this.

cheers,
Ken

On 8/30/07, Kenneth McDonald [email protected] wrote:

Having said that, here’s my first entry. I think it’s utterly stupid
(can you tell I just wasted some time tracking this down?) that

"abc"[0] == "a"

is false. Why doesn’t that work? Because, with a single index, the array
access operator on a string returns, not the character at the given
position, but the character code of the character at that position.

It would be useful if you actually looked what’s happening in the
future: this will be changed for Ruby 1.9. It is, in fact, a sensible
choice to make given the nature of strings in Ruby.

-austin

From: Kenneth McDonald [mailto:[email protected]]

“abc”[0] == “a” is false.

ruby is dynamic, and so is this community, and the change is good.

http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l101

kind regards -botp

Kenneth McDonald wrote:

Here’s hoping someone out there avoids this mistake after reading this.

Not to rain on the Stupid Parade, but the ruby-talk and ruby-core list
archives (and the RCR archive, too) are full of such threads.

In the best cases, summary information gets written up on the Ruby
Garden wiki to help others on their way. If your particular issue is
not yet there, perhaps you could be Good Ruby Citizen and add it.

If you really want to make a point about one other other “stupid” Ruby
feature, please be sure to first read the prior threads.


James B.

“Discover the recipes you are using and abandon them.”

  • Brian Eno and Peter Schmidt, Oblique Strategies

It is a matter of how you look at it:

irb(main):002:0> “abc”[0,1] == “a”
=> true

by
TheR

Kenneth McDonald wrote:

think it’s fair to give a reason something you mention as a Ruby
array access operator on a string returns, not the character at the
given position, but the character code of the character at that
position.

I admit that I’ve faced this one before :slight_smile:

Cheers,
Mohit.
8/31/2007 | 12:13 PM.

On 8/31/07, Damjan R. [email protected] wrote:

It is a matter of how you look at it:

irb(main):002:0> “abc”[0,1] == “a”
=> true

It’s a matter that is fixed already, and waiting for you under the
christmas tree:

[manveru@pi ~]$ RUBYOPT= irb19
[RUBY_VERSION, RUBY_PLATFORM, RUBY_RELEASE_DATE]

[“1.9.0”, “i686-linux”, “2007-08-28”]

“foo”[0]

“f”

“foo”[0] == “f”

true

^ manveru

On Fri, 31 Aug 2007 12:31:41 +0900, Austin Z. wrote:

It would be useful if you actually looked what’s happening in the
future: this will be changed for Ruby 1.9. It is, in fact, a sensible
choice to make given the nature of strings in Ruby.

-austin

If it were a sensible choice, why change it? Sounds pretty stupid to
me!


Chris G.

“Not everything that can be counted counts, and not everything
that counts can be counted.” - Albert Einstein

On 31.08.2007 05:24, Kenneth McDonald wrote:

Having said that, here’s my first entry. I think it’s utterly stupid
(can you tell I just wasted some time tracking this down?) that

“abc”[0] == “a”

You can change that behavior yourself without installing >=1.9

class String
alias :old_index :[]
def
a.length==1 ? old_index(*a).chr : old_index(a)
end
def asc # this is from [1]
case size
when 0; nil
when 1; old_index(0)
else unpack 'c

end
end
end

“abc”[0] == “a” # → true
“abc”[1] == “b” # → true
“abc”[0,1] == “a” # → true
“a”.asc == 97 # → true
“abc”.asc == [97,98,99] # → true

But certainly this may break existing libs, so be careful.

[1] http://forum.ruby-portal.de/viewtopic.php?p=2654#2654

  • Matthias

Hi –

On Mon, 3 Sep 2007, Matthias Wächter wrote:

def

“abc”[0] == “a” # -> true
“abc”[1] == “b” # -> true
“abc”[0,1] == “a” # -> true
“a”.asc == 97 # -> true
“abc”.asc == [97,98,99] # -> true

But certainly this may break existing libs, so be careful.

The problem is, you can’t be careful. You can only decide that it’s OK
for code to break, and keep your fingers crossed that it doesn’t.

I don’t mean to split hairs – of course “careful” can mean lots of
things. It’s just that I think it’s important to remember that the
code doesn’t “know” that the person who changed it is worried :slight_smile: It’s
just going to do what it does. So unless you’re willing to read
through the entire source code base, for Ruby and all add-on
libraries, every time you make such a change, you’re pretty much
accepting some very real risk.

David

[email protected] schrieb:

But certainly this may break existing libs, so be careful.

The problem is, you can’t be careful. You can only decide that it’s OK
for code to break, and keep your fingers crossed that it doesn’t.

Sure. Whenever you extend a basic class you take the risk of breaking
something. Choosing a name for a function or an alias when you extend a
function is nontrivial if you want to take into account that the name
can already be used.

I don’t mean to split hairs – of course “careful” can mean lots of
things. It’s just that I think it’s important to remember that the
code doesn’t “know” that the person who changed it is worried :slight_smile:

:slight_smile:

It’s
just going to do what it does. So unless you’re willing to read
through the entire source code base, for Ruby and all add-on
libraries, every time you make such a change, you’re pretty much
accepting some very real risk.

I think that is what everyone who writes libraries has to do for 1.9/2.0
anyway.

  • Matthias

Hi –

On Tue, 4 Sep 2007, Matthias Wächter wrote:

[email protected] schrieb:

But certainly this may break existing libs, so be careful.

The problem is, you can’t be careful. You can only decide that it’s OK
for code to break, and keep your fingers crossed that it doesn’t.

Sure. Whenever you extend a basic class you take the risk of
breaking something. Choosing a name for a function or an alias when
you extend a function is nontrivial if you want to take into account
that the name can already be used.

I guess what I wonder is: what does it mean to take that into account?
If it affects our decisions, then we should always decide not to –
and all the more for actually changing the behavior of existing
methods.

accepting some very real risk.

I think that is what everyone who writes libraries has to do for
1.9/2.0 anyway.

I definitely don’t discourage reading through the source :slight_smile: But it’s
very hard to check reliably to see (for example) whether there’s any
case where someone relies on the behavior of String#[], or gsub!
returning nil, or whatever. And it could change…

I have to add that I’m just thinking out loud about things that have
been tossed around for years – it’s not really a specfic critique of
what you said, more that I’ve never quite understood what it actually
means, in practical terms, when people say that one should be
careful about making core changes, or not do it lightly, or “With
great power comes great responsibility”, etc. It’s partly why I like
#extend so much – it limits the changes to individual objects.

David

John J. wrote:

Indeed, at some point you simply have to break things to do new or
better or different things. Endless backwards compatibility ends up
with bloated, hacked up junk.

Change is good, as long as it is documented and changed for the better
when it
breaks stuff.

Look at C, the changes can be quite extreme between old old code and new
code.
But I think it was worth it. Then look at Windows, hell I think the C:\
thing
was stolen from 1960s OSes by DEC. Windows NT has to be compatible with
users
minds and old versions software… Blast you can still run edit from an
XP
machine.

Personally, as long as the changes are documented, fair warning is given
before breaking code written last week, and the updates to software come
into
wide spread usage. I don’t give a darn hehe.

Just my two cents.

TerryP.

If there is a good reason for changes, and people find the changes
truly useful, it will survive. Otherwise it will become a dusty book
in the library. Lots of commercial language/compiler producers have
tried to have it both ways to please customers and sometimes to lock
them in to an upgrade cycle. With Ruby though, if the new stuff is a
problem, stick with the old stack.

Sometimes, if it ain’t broke, don’t fix it. (hence the long life of
COBOL)

Indeed, at some point you simply have to break things to do new or
better or different things. Endless backwards compatibility ends up
with bloated, hacked up junk.

On Tue, Sep 04, 2007 at 04:23:06AM +0900, Matthias W?chter wrote:

It’s
just going to do what it does. So unless you’re willing to read
through the entire source code base, for Ruby and all add-on
libraries, every time you make such a change, you’re pretty much
accepting some very real risk.

I think that is what everyone who writes libraries has to do for 1.9/2.0 anyway.

Except that 1.9 makes an attempt to break as little code as possible
while still providing the new feature, so:

“abc”[0] == ?a

is true in both 1.8 and 1.9. It’s not true with your code.

Putting the burden on the user to make their code comply with your
library is a mean thing to do, IMO. It’s why I dislike mathn so much.
If you can get the new behavior without requiring the user to change
their code, then you’re in a much better situation.

I think this is where selector namespaces will come in very handy, once
we have them.

Paul