From: Pit Capitain Date: 2003-08-07T16:13:30+09:00 Subject: Re: What's New and Shiny in Ruby 1.8.0? On 7 Aug 2003 at 8:30, Harry Ohlsen wrote: > Martin DeMello wrote: > > > Still hacky, but general: > > > > class Test > > attr_accessor :foo, :bar > > def initialize(f, b) > > @foo, @bar = f, b > > end > > > > def inspect > > "[#{foo}, #{bar}]" > > end > > end > > > > def rev(obj) > > a = obj.dup > > class << a > > alias old_cmp <=> > > def <=>(other) > > -old_cmp(other) > > end > > end > > a > > end > > > > a = [ > > Test.new("Hello", 1), > > Test.new("World", -1), > > Test.new("Foo", 5), > > Test.new("bar", 4) > > ] > > > > p a > > p a.sort_by {|x| x.foo} > > p a.sort_by {|x| rev(x.foo)} Very nice idea. I like it. > However, if we try > > p a.sort_by { |x| rev(x.bar) } > > we get ... > > sort_by.rb:20:in `dup': can't dup Fixnum (TypeError) This could be fixed with something like def rev(obj) -obj rescue NoMethodError a = obj.dup class << a alias old_cmp <=> def <=>(other) -old_cmp(other) end end a end Not beautiful, but working. > I tried sticking in an > > if obj.respond_to? :dup > > but that didn't help. It would appear that, while Fixnum responds to > #dup, its response is "I'm sorry, Dave, I'm afraid I can't do that." > :-(. > > That doesn't seem to make a lot of sense to me. I would have thought > it made more sense for Fixnum#dup to just return self. Maybe there's > some good reason for not doing that. But then you couldn't do things like Martin's code, where you want to modify a duplicate and not the original object. > Alternatively, maybe we need a way for classes to disown methods they > inherit that they don't want to (or logically shouldn't) implement? > Then, Fixnum could disown dup and the respond_to? test would work the > way I was expecting. Since dup is defined in Object (Kernel), you'd expect to find it in every object, wouldn't you? But if you really want you can undefine dup for Fixnums: p 5.respond_to?( :dup ) # => true p 5.dup rescue puts $! # => can't dup Fixnum Fixnum.send :undef_method, :dup p 5.respond_to?( :dup ) # => false p 5.dup rescue puts $! # => undefined method `dup' for 5:Fixnum Regards, Pit