Forum: Ruby overloading sort_by (blocks question)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Caf38c89d40443a858741b61ac6d82de?d=identicon&s=25 Dan Zwell (Guest)
on 2007-05-16 22:50
(Received via mailing list)
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
47694fa0220a629040b814342725e1ba?d=identicon&s=25 Mark Day (Guest)
on 2007-05-16 23:07
(Received via mailing list)
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
Caf38c89d40443a858741b61ac6d82de?d=identicon&s=25 Dan Zwell (Guest)
on 2007-05-16 23:27
(Received via mailing list)
Thanks, that worked immediately.

Dan
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2007-05-16 23:34
(Received via mailing list)
On 5/16/07, Dan Zwell <dzwell@gmail.com> 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/
Caf38c89d40443a858741b61ac6d82de?d=identicon&s=25 Dan Zwell (Guest)
on 2007-05-16 23:47
(Received via mailing list)
>
>           @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
This topic is locked and can not be replied to.