TypeError: can't convert into Array
-
@thomthom said:
I got a custom class inherited that include Enumerable. The class also has a
#to_a
method.
...
Granted it's not an Array, but it says it cannot convert the object - which makes me wonder why since it has an#to_a
method.The
#to_a
method can come from more than one ancestor.For instance... the basic source of the
#to_a
method, comes fromObject
which states:
@unknownuser said:Returns an array representation of obj. For objects of class
Object
and others that don’t explicitly override the method, the return value is an array containingself
. However, this latter behavior will soon be obsolete.
This implies that custom classes need to override the#to_a
method, so Ruby can know how to do the conversion.OR... the
#to_a
method can come fromArray
, if the custom class, is some descendant level subclass ofArray
. Which, referring to the docs:
@unknownuser said:Returns
self
. If called on a subclass ofArray
, converts the receiver to anArray
object.
Note: ThatArray
itself, hasEnumerable
mixed in, but it appears (looking at the C source,) that the "mixing" is done first.. then theArray
class definition overrides the method inherited fromEnumerable
, with it's own edition of the method. -
@jim said:
I think Enumerable requires that your class implement a
.each
method. Some Enumerable methods also need a<=>
method (comparison) defined.I do have an .each method implemented. But in any case would that matter for converting to an Array?
I manually added an #to_a method to my that returns an array. So I don't understand why it raises this error...
-
You need to
yield
in your.each
iterator.Something like this (not tested.)
@entities.each{|e| yield(e)}
See also: block_given?
Here's a related article about the performance of passing blocks: http://mudge.github.com/2011/01/26/passing-blocks-in-ruby-without-block.html
-
@thomthom said:
I manually added an
#to_a
method to my [class] that returns an array. So I don't understand why it raises this error...Is the superclass one of those API C++ collection classes ? Most of these give us problems when we try to subclass them.
-
@jim said:
You need to
yield
in your.each
iterator.It does that.
But I fail to see why
.each
got to do with converting to an array when I have a.to_a
method ... ? I've been searching for info on it, but I cannot find anything. -
@thomthom said:
It does that.
Sorry, I was looking at your latest bitbucket repo, which must not be your latest version.
-
No - it's still on my computer. A larger rewrite. The one at the repo was just an early framework WIP.
-
A simplified example:
<span class="syntaxdefault"></span><span class="syntaxkeyword">class </span><span class="syntaxdefault">Foo</span><span class="syntaxkeyword">; </span><span class="syntaxdefault">def to_a</span><span class="syntaxkeyword">; [</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">2</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">3</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">4</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">5</span><span class="syntaxkeyword">]; </span><span class="syntaxdefault">end</span><span class="syntaxkeyword">; </span><span class="syntaxdefault">end</span><span class="syntaxkeyword">;<br /></span><span class="syntaxdefault">nil<br /><br />f</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">Foo</span><span class="syntaxkeyword">.new<br /></span><span class="syntaxcomment">#<Foo;0x15259760><br /><br /></span><span class="syntaxdefault">x</span><span class="syntaxkeyword">=[</span><span class="syntaxdefault">3</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">4</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">5</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">6</span><span class="syntaxkeyword">]<br />[</span><span class="syntaxdefault">3</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">4</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">5</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">6</span><span class="syntaxkeyword">]<br /><br /></span><span class="syntaxdefault">x </span><span class="syntaxkeyword">| </span><span class="syntaxdefault">f<br />Error</span><span class="syntaxkeyword">; </span><span class="syntaxcomment">#<TypeError; (eval);155;in `|'; can't convert Foo into Array><br /></span><span class="syntaxkeyword">(eval);</span><span class="syntaxdefault">155<br /></span><span class="syntaxkeyword">(eval);</span><span class="syntaxdefault">155</span>
Off course,
x | f.to_a
works, but since the error message indicate some conversion was tried, I wonder why the.to_a
method wasn't used. -
use
.to_ary
although I don't have a good explanation yet.class Foo def to_ary [1,2,3,4,5] end end
This is as close to an explanation as I could find: http://stackoverflow.com/questions/766712/make-an-object-behave-like-an-array-for-parallel-assignment-in-ruby/768201#768201
-
Thanks!
@unknownuser said:
Returns a new array. In the first form, the new array is empty. In the second it is created with size copies of obj (that is, size references to the same obj). The third form creates a copy of the array passed as a parameter (the array is generated by calling to_ary on the parameter). In the last form, an array of the given size is created. Each element in this array is calculated by passing the element’s index to the given block and storing the return value
So it appears what happens is not that
f.to_a
is called, but insteadArray.new( f )
- andArray.new
uses.to_ary
. -
@thomthom said:
So it appears what happens is not that
f.to_a
is called, but insteadArray.new( f )
- andArray.new
uses.to_ary
.Actually (if you use the CHM Ruby refdoc,) the source shows that the
#|
method explicitly calls:
%(#0000BF)[arg2 = to_ary(arg2);]
ie, it makes a copy of the second arg to use locally (within its body.)
Advertisement