# Overloading sort\_by (blocks question)

**URL:** <https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341>\
**Category:** Ruby\
**Created:** [May 16, 2007, 10:50pm UTC](https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341 "2007-05-16T22:50:23Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![cmaj135](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/8edcca/32.png) [@cmaj135](https://www.ruby-forum.com/u/cmaj135)\
**Post date:** [May 16, 2007, 10:50pm UTC](https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341/1 "2007-05-16T22:50:23Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![cmaj135](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/8edcca/32.png) [@cmaj135](https://www.ruby-forum.com/u/cmaj135)\
**Post date:** [May 16, 2007, 11:07pm UTC](https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341/2 "2007-05-16T23:07:24Z")

</div>

On May 16, 2007, at 1:49 PM, Dan Z. 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:  
>   
> 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

---

<div class="post-metadata">

**Author:** ![cmaj135](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/8edcca/32.png) [@cmaj135](https://www.ruby-forum.com/u/cmaj135)\
**Post date:** [May 16, 2007, 11:27pm UTC](https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341/3 "2007-05-16T23:27:26Z")

</div>

Thanks, that worked immediately.

Dan

---

<div class="post-metadata">

**Author:** ![cmaj135](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/8edcca/32.png) [@cmaj135](https://www.ruby-forum.com/u/cmaj135)\
**Post date:** [May 16, 2007, 11:47pm UTC](https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341/4 "2007-05-16T23:47:28Z")

</div>

> ```
> @array = array
> end
> 
> def to_pairs
> 
> ```

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

---

<div class="post-metadata">

**Author:** ![cmaj135](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/8edcca/32.png) [@cmaj135](https://www.ruby-forum.com/u/cmaj135)\
**Post date:** [May 16, 2007, 11:34pm UTC](https://www.ruby-forum.com/t/overloading-sort-by-blocks-question/104341/5 "2007-05-16T23:34:27Z")

</div>

On 5/16/07, Dan Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> self.replace(ary)
> 
> ```
> 
> 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.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
