[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

overloading sort_by (blocks question

Dan Zwell

5/16/2007 8:50:00 PM

Hi, all,

I have subclassed Array to add some features. I am redefining sort_by so
that it does not return an Array but a Pairs (my subclass), but I cannot
get the syntax for passing the blocks right.

Here's my code:

class Pairs < Array
def initialize(ary)
self.replace(ary)
end

alias_method :sort_by_old, :sort_by
# PROBLEM here:
def sort_by(&block)
ary = self.sort_by_old {yield(block)}
Pairs.new(ary)
end
end

I just want Pairs#sort_by to return a Pairs object every time it is
called. Could anybody help me?

Thanks,
Dan

4 Answers

Mark Day

5/16/2007 9:07:00 PM

0

On May 16, 2007, at 1:49 PM, Dan Zwell wrote:

> I have subclassed Array to add some features. I am redefining
> sort_by so that it does not return an Array but a Pairs (my
> subclass), but I cannot get the syntax for passing the blocks right.
>
> Here's my code:
<snip>
> alias_method :sort_by_old, :sort_by
> # PROBLEM here:
> def sort_by(&block)
> ary = self.sort_by_old {yield(block)}
> Pairs.new(ary)
> end

Use this instead:
ary = self.sort_by_old(&block)

>> p=Pairs["abcd", "efg", "hi", "j"]
=> ["abcd", "efg", "hi", "j"]
>> p.class
=> Pairs
>> q=p.sort_by{|x| x.length}
=> ["j", "hi", "efg", "abcd"]
>> q.class
=> Pairs

-Mark


Dan Zwell

5/16/2007 9:27:00 PM

0

Thanks, that worked immediately.

Dan

Mark Day wrote:
> On May 16, 2007, at 1:49 PM, Dan Zwell wrote:
>
>> I have subclassed Array to add some features. I am redefining sort_by
>> so that it does not return an Array but a Pairs (my subclass), but I
>> cannot get the syntax for passing the blocks right.
>>
>> Here's my code:
> <snip>
>> alias_method :sort_by_old, :sort_by
>> # PROBLEM here:
>> def sort_by(&block)
>> ary = self.sort_by_old {yield(block)}
>> Pairs.new(ary)
>> end
>
> Use this instead:
> ary = self.sort_by_old(&block)
>
> >> p=Pairs["abcd", "efg", "hi", "j"]
> => ["abcd", "efg", "hi", "j"]
> >> p.class
> => Pairs
> >> q=p.sort_by{|x| x.length}
> => ["j", "hi", "efg", "abcd"]
> >> q.class
> => Pairs
>
> -Mark
>
>
>

Rick DeNatale

5/16/2007 9:34:00 PM

0

On 5/16/07, Dan Zwell <dzwell@gmail.com> wrote:
> Hi, all,
>
> I have subclassed Array to add some features. I am redefining sort_by so
> that it does not return an Array but a Pairs (my subclass), but I cannot
> get the syntax for passing the blocks right.
>
> Here's my code:
>
> class Pairs < Array
> def initialize(ary)
> self.replace(ary)
> end
>
> alias_method :sort_by_old, :sort_by
> # PROBLEM here:
> def sort_by(&block)
> ary = self.sort_by_old {yield(block)}
> Pairs.new(ary)
> end
> end
>
> I just want Pairs#sort_by to return a Pairs object every time it is
> called. Could anybody help me?
>
> Thanks,
> Dan
>
>

def sort_by(&block)
Pairs.new(self.sort_by_old(&block))
end

This should solve your block passing problem.

However, I'd strongly suggets rethinking making a subclass of array
In most cases its better to use delegation to an array instance
variable.

Something like:

require 'forwardable'

class Pairs
extend Forwardable

# For methods which you would not have overriden in the subclass
# simply delegate to the instance variable @array
# this is just an example, the division between methods which are
# simply delegated, which are replaced and which are wrapped is up
# to you.
def_delegators(:@array, :[], :[]=, :+ #...

# I notice that your initialize method doesn't seem to take the same
# argument as Array so ...
def initialize(array)
@array = array
end
=begin
# If you wanted to have the same protocol for creating your class
# as Array then you'd need something like this.
def initialize(*args, &block)
@array = Array.new(*args, &block)
end

def self.[](*objs)
new().replace(Array[*objs])
end
=end

def replace(other_array)
self.array = other_array.to_ary # use to_ary instead of to_a
end

# to_ary is used for internal conversions of objects
def to_ary
array
end

# For a method which was replaced in your subclass just replace
# explicit (or implicit) self with @array
def concat(other_arr)
array.concat(other_arr.to_pairs)
end

def sort_by(&b)
Pairs.new(@array.sort_by(&b))
end

def to_pairs
self
end

end

class Array
def to_pairs
Pairs.new(self)
end
end



--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Dan Zwell

5/16/2007 9:47:00 PM

0

> I'd strongly suggets rethinking making a subclass of array
> In most cases its better to use delegation to an array instance
> variable.
>
> Something like:
>
> require 'forwardable'
>
> class Pairs
> extend Forwardable
>
> # For methods which you would not have overriden in the subclass
> # simply delegate to the instance variable @array
> # this is just an example, the division between methods which are
> # simply delegated, which are replaced and which are wrapped is up
> # to you.
> def_delegators(:@array, :[], :[]=, :+ #...
>
> # I notice that your initialize method doesn't seem to take the same
> # argument as Array so ...
> def initialize(array)
> @array = array
> end
> =begin
> # If you wanted to have the same protocol for creating your class
> # as Array then you'd need something like this.
> def initialize(*args, &block)
> @array = Array.new(*args, &block)
> end
>
> def self.[](*objs)
> new().replace(Array[*objs])
> end
> =end
>
> def replace(other_array)
> self.array = other_array.to_ary # use to_ary instead of to_a
> end
>
> # to_ary is used for internal conversions of objects
> def to_ary
> array
> end
>
> # For a method which was replaced in your subclass just replace
> # explicit (or implicit) self with @array
> def concat(other_arr)
> array.concat(other_arr.to_pairs)
> end
>
> def sort_by(&b)
> Pairs.new(@array.sort_by(&b))
> end
>
> def to_pairs
> self
> end
>
> end
>
> class Array
> def to_pairs
> Pairs.new(self)
> end
> end
>
>
>

Thanks for the code examples--I previously didn't understand exactly how
delegation worked. This looks neat. I'll be playing with this and will
most likely use it.

Thanks again,
Dan