April 22, 2008 at 10:01 pm
· Filed under rubinius, ruby
Section 3.4.2 of The Ruby Programming Language talks about defining (or overriding) the hash and eql? methods of a class in order to control how objects are treated as keys in a hash… except for strings. Strings are handled specially because they’re “mutable but commonly used as hash keys.”
So when someone asked today on comp.lang.ruby about case-insensitive hash access, the answer, sadly, could not be as simple (and possibly dangerous) as “Just override hash and eql? in String.” Or could it?
Well, I whipped up something quickly:
class String
alias old_hash hash
def hash
self.downcase.old_hash
end
def eql?(other)
self.hash == other.hash
end
end
require ‘test/unit‘
class TestCaseInsensitiveHashAccess < Test::Unit::TestCase
def test_case_insensitivity
h = {’a‘ => 1, ‘B‘ => ‘buzz‘}
assert_equal(1, h[’A‘])
assert_equal(’buzz‘, h[’b‘])
end
end
I ran it a few times. Ruby failed. Ruby 1.9 failed. JRuby failed. But Rubinius passed.
And why shouldn’t it pass? For every other class, this sort of monkeying with hash and eql? will get you what you want: hash key access mayhem. Why not String?
Well, there might be something sinister hiding in the “mutable but commonly used as hash keys” description. Something subtle. Maybe it’s not subtle and I just haven’t been thinking very clearly. I don’t know.
It looks to me, in the short amount of time I’ve been thinking about this, that Rubinius is more consistently Ruby-ish than Ruby is (at least in this case). Are there more ways in which that’s true?
Permalink
April 12, 2008 at 1:33 pm
· Filed under metaprogramming, ruby
Let’s say you’re crazy. Now, as a crazy person, you might have a method like this:
def greet_world(salutation=”Hello“)
“#{salutation} World!“
end
You’re not so crazy that you can’t write working Ruby code. Anyway, it’s totally useful:
greet_world
greet_world(’Hi‘)
greet_world(’Yo‘)
greet_world(’Hola‘)
But then you see someone do this:
greet_world(’Hello‘)
And it drives you even crazier. Being totally crazy, you feel a compulsion to make fun of people who pass the default value for an argument of a method. But how in the world can you tell?
Well, it turns out (and you probably know this already) that the argument list of a method is a proper venue for executing code. You know this because you’ve seen this a thousand times: def something(time=Time.now). That Time.now happens when you call the method without that optional argument. It doesn’t happen when Ruby first parses the method and adds it to the method table for the class. That wouldn’t be too helpful.
So… you can execute arbitrary code in the method argument list. But what kind? What’s the scope? Well, anything you can do in a method body is fair game (and anything you can’t is not). You can’t define a class, for instance. And the scope? The method body itself.
You’re crazy, remember? But not so crazy that you don’t remember that every statement has a return value. Like assignment. Assignment returns a value. And you’ve got a place in the argument list that’s scoped with the method body. And you’ve got a deep desire to mock people who pass default values.
BOOM!
def greet_world(salutation=(salutation_not_given=’Hello‘))
if salutation == ‘Hello‘ and not salutation_not_given
“YOU HAVE NO IMAGINATION!“
else
“#{salutation} World!“
end
end
greet_world(’Hello‘)
greet_world
greet_world(’Hi‘)
salutation_not_given is nil if you’ve given a value. It’s one of those things.
ANYWAY. Use that at your own peril.
Permalink
April 6, 2008 at 5:09 pm
· Filed under GuessMethod, ruby
Confreaks have started putting up more video from MountainWest RubyConf, and today saw the addition of the lightning talks from day one. I’d like to draw particular attention to the second entry of this list of who talked when about what:
- Binary Lottery in Shoes - Mike Moore - 0:10
- GuessMethod - Chris Shea (me!) - 4:35
- ActiveScaffold - Ed Moss - 8:51
- Migration Concordance - Josh Susser - 12:39
- Framework Components - Jeremy McAnally - 18:05
- Systems Building Systems with Puppet - Andrew Schafer - 20:43
- Multi-image Uploading with SWFUpload and Rails - David South - 27:14
- RubyAmp: Ruby Dev in TextMate Amplified - Tim Harper - 31:55
- Build a GUI App in 5 Minutes - David Koontz - 37:46
Lots of interesting stuff in there. And I encourage everyone to look at other videos from the conference. It was great.
Permalink