[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Enumberable fails for class Subclass < Array; def enum...

Laza

7/10/2006 6:04:00 AM

Array includes Enumerable. But when a subclass of Array redefines
each(), then Enumerable still refers to the original Array.each(). Why
is that?
For example:

class RangeUnion < Array
def each
super{|x| x.each{|i| yield i} }
end
end

# u = RangeUnion[1..3, 11..13, "a".."c"]
# u.each{|x| print "#{x} "} # THIS WORKS
# #=> 1 2 3 11 12 13 a b c
#
# u.collect{|x| x} # THIS FAILS!!!
# #=> [1, 2, 3, 11, 12, 13, "a", "b", "c"] # expected
# #=> [1..3, 11..13, "a".."c"] # actual

In the example above, each() is redefined. But collect() does not use
the redefined each()!!! It uses Array.each(). Subclassing from some
other class works fine:

class RangeUnion < NotAnArray; ... # gives expected result

It seems that Enumerable is hardwired (built in) in Array. But subclass
should be able to override it. Why isn't that possible?

-Laza

4 Answers

Nobuyoshi Nakada

7/10/2006 6:48:00 AM

0

Hi,

At Mon, 10 Jul 2006 15:05:11 +0900,
Laza wrote in [ruby-talk:201045]:
> class RangeUnion < Array
define_method(:collect, Enumerable.instance_method(:collect))
> def each
> super{|x| x.each{|i| yield i} }
> end
> end

--
Nobu Nakada

Daniel Schierbeck

7/10/2006 9:42:00 AM

0

Laza wrote:
> Array includes Enumerable. But when a subclass of Array redefines
> each(), then Enumerable still refers to the original Array.each(). Why
> is that?
> For example:
>
> class RangeUnion < Array
> def each
> super{|x| x.each{|i| yield i} }
> end
> end
>
> # u = RangeUnion[1..3, 11..13, "a".."c"]
> # u.each{|x| print "#{x} "} # THIS WORKS
> # #=> 1 2 3 11 12 13 a b c
> #
> # u.collect{|x| x} # THIS FAILS!!!
> # #=> [1, 2, 3, 11, 12, 13, "a", "b", "c"] # expected
> # #=> [1..3, 11..13, "a".."c"] # actual
>
> In the example above, each() is redefined. But collect() does not use
> the redefined each()!!! It uses Array.each(). Subclassing from some
> other class works fine:
>
> class RangeUnion < NotAnArray; ... # gives expected result
>
> It seems that Enumerable is hardwired (built in) in Array. But subclass
> should be able to override it. Why isn't that possible?

I've experienced problems myself when trying to redefine some of
Enumerable's methods. Apparently Array uses its own #collect and #map
methods, plus some others. Maybe if you explicitly re-include Enumerable
into your subclass?


Cheers,
Daniel

Daniel DeLorme

7/10/2006 1:43:00 PM

0

Laza wrote:
> Array includes Enumerable. But when a subclass of Array redefines
> each(), then Enumerable still refers to the original Array.each(). Why
> is that?

Your confusion is understandable but you've got the problem backward: that
behavior is not because Enumerable uses Array's each, it's because Array defines
its own version of collect. Look at Array's local (non-inherited) methods:

[].public_methods(false).sort
=> ["&", "*", "+", "-", "<<", "<=>", "==", "[]", "[]=", "assoc", "at", "clear",
"collect", "collect!", "compact", "compact!", "concat", "delete", "delete_at",
"delete_if", "each", "each_index", "empty?", "eql?", "fetch", "fill", "first",
"flatten", "flatten!", "frozen?", "hash", "include?", "index", "indexes",
"indices", "insert", "inspect", "join", "last", "length", "map", "map!",
"nitems", "pack", "pop", "push", "rassoc", "reject", "reject!", "replace",
"reverse", "reverse!", "reverse_each", "rindex", "select", "shift", "size",
"slice", "slice!", "sort", "sort!", "to_a", "to_ary", "to_s", "transpose",
"uniq", "uniq!", "unshift", "values_at", "zip", "|"]

I suppose it was done that way for optimization. Why do you need to subclass
Array, anyway?

Daniel

Laza

7/10/2006 5:33:00 PM

0

re-including Enumerable does not help. I re-implemented the class by
having an Array member variable instead of inheriting from Array class.
Apparently, not all classes are created equal in Ruby.

Daniel Schierbeck wrote:
> I've experienced problems myself when trying to redefine some of
> Enumerable's methods. Apparently Array uses its own #collect and #map
> methods, plus some others. Maybe if you explicitly re-include Enumerable
> into your subclass?
>
>
> Cheers,
> Daniel