raganwald
(This is a snapshot of my old weblog. New posts and selected republished essays can be found at raganwald.com.)

Friday, December 28, 2007
  Something in Ruby that bit me at work today


The methods :class and :dup are a bit of a leaky abstraction when used in combination with an object’s Singleton Class:

class Marx
def jokes (laughs)
laughs * 2
end
end

groucho = Marx.new
chico = groucho.dup

puts "#{groucho.jokes(10)} == #{chico.jokes(10)}"

def groucho.jokes (laughs)
laughs / 2
end

harpo = groucho.dup

puts "#{groucho.jokes(10)} != #{harpo.jokes(10)}"
puts "...but #{harpo.jokes(10)} == #{chico.jokes(10)}"
puts "because Groucho is still considered a #{groucho.class}"
 

Comments on “Something in Ruby that bit me at work today:
This post has been removed by the author.
 
This gets me now and then in Ruby. It's one of those things that, once you understand it, it makes sense, but before you understand it you wouldn't immediately intuit it.

At first it feels like a POLS violation (Principle of Least Surprise) but then you see that it could go two ways and there's no clear way to know beforehand which one is right--and often that the way that bit you makes more sense coming from the "language up" rather than from the "problem down".

I call this a POOY violaton. ("This is clearly a violation of the Principle Of... Oh... Yeah.")

Edit: Now with 33% more correctly acronymized letters!
 
This post has been removed by the author.
 
Yes, that's the desired behavior of Ruby IIRC. And if you want the singleton class be copied, you need to use clone instead of dup.o
 
Redefining methods on namespaces is complicated; as other commenters have mentioned, you can't consider this a violation of least surprise because no one quite knows what to expect.

It's nice if certain namespaces can't change in a given context. Ruby's :class and :dup both more or less assume invariance - and it's kinda hard to see what those should do if that invariant is broken.

If you restrict your redefinitions to a 'preamble', for example of a language extension/library (like say, rails), or for your own project, you don't usually run into these problems.
 
If you restrict your redefinitions to a 'preamble', for example of a language extension/library (like say, rails), or for your own project, you don't usually run into these problems.

Except, even in a preamble this will be a problem. It doesn't matter where you bind methods to an object, the default dup method will never create objects with your methods, because dup works from the class of the object, and the class does not capture the singleton class.

I guess the real gotcha here is that objects have singleton classes, but that the .class method does not return them, and that methods like dup are tied to the class and not the singleton class.
 




<< Home
Reg Braithwaite


Recent Writing
Homoiconic Technical Writing / raganwald.posterous.com

Books
What I‘ve Learned From Failure / Kestrels, Quirky Birds, and Hopeless Egocentricity

Share
rewrite_rails / andand / unfold.rb / string_to_proc.rb / dsl_and_let.rb / comprehension.rb / lazy_lists.rb

Beauty
IS-STRICTLY-EQUIVALENT-TO-A / Spaghetti-Western Coding / Golf is a good program spoiled / Programming conventions as signals / Not all functions should be object methods

The Not So Big Software Design / Writing programs for people to read / Why Why Functional Programming Matters Matters / But Y would I want to do a thing like this?

Work
The single most important thing you must do to improve your programming career / The Naïve Approach to Hiring People / No Disrespect / Take control of your interview / Three tips for getting a job through a recruiter / My favourite interview question

Management
Exception Handling in Software Development / What if powerful languages and idioms only work for small teams? / Bricks / Which theory fits the evidence? / Still failing, still learning / What I’ve learned from failure

Notation
The unary ampersand in Ruby / (1..100).inject(&:+) / The challenge of teaching yourself a programming language / The significance of the meta-circular interpreter / Block-Structured Javascript / Haskell, Ruby and Infinity / Closures and Higher-Order Functions

Opinion
Why Apple is more expensive than Amazon / Why we are the biggest obstacles to our own growth / Is software the documentation of business process mistakes? / We have lost control of the apparatus / What I’ve Learned From Sales I, II, III

Whimsey
The Narcissism of Small Code Differences / Billy Martin’s Technique for Managing his Manager / Three stories about The Tao / Programming Language Stories / Why You Need a Degree to Work For BigCo

History
06/04 / 07/04 / 08/04 / 09/04 / 10/04 / 11/04 / 12/04 / 01/05 / 02/05 / 03/05 / 04/05 / 06/05 / 07/05 / 08/05 / 09/05 / 10/05 / 11/05 / 01/06 / 02/06 / 03/06 / 04/06 / 05/06 / 06/06 / 07/06 / 08/06 / 09/06 / 10/06 / 11/06 / 12/06 / 01/07 / 02/07 / 03/07 / 04/07 / 05/07 / 06/07 / 07/07 / 08/07 / 09/07 / 10/07 / 11/07 / 12/07 / 01/08 / 02/08 / 03/08 / 04/08 / 05/08 / 06/08 / 07/08 /