Weird compile error: Illegal EachIn expression

BlitzMax Forums/BlitzMax Programming/Weird compile error: Illegal EachIn expression

Pineapple(Posted 2013) [#1]
I get that compile error when attempting to run this:

For Local t$=EachIn hash.ObjectEnumerator()
	Print t
Next


While this compiles fine and works as expected:

For Local t$=EachIn hash
	Print t
Next


What's going on?

Here's the rest of the code.




Brucey(Posted 2013) [#2]
I believe ObjectEnumerator() is a "private" method which implements the enumeration stuff, but which you don't use yourself.
When you use Eachin, BlitzMax expects the argument to be of a certain structure - either an array or an Object which has the enumeration functionality.


Yasha(Posted 2013) [#3]
To put it another way: EachIn calls ObjectEnumerator on the object passed as collection. If you call ObjectEnumerator yourself, you're no longer passing a collection that can be enumerated by EachIn (unless you work some naughtiness so that your enumerator is also a collection, which is conceptually just plain wrong); the thing you're passing has the wrong structure for what EachIn expects to do with it (but you don't get a type error because this is implemented separately from type checking; in Monkey you would presumably get a type error indicating the wrong interface).

It's a type error, with a weird message. An enumerator is not a collection.


Analogous situation: say you have a function that returns the width of an image prepended with "Foo":

Strict

Function Foopify:String(img:TImage)
    Return "Foo " + ImageWidth(img)
End Function

Local img:TImage = CreateImage(256, 256)

Print Foopify(img)        ' Fine, prints "Foo 256"

Print Foopify(ImageWidth(img))    ' Type error: we need a TImage, not a number


By trying to do one step of the internal process yourself, you change the type of the value and render the whole thing invalid. BlitzMax doesn't actually call it a type error because its type system doesn't include interfaces, but it is the same thing.


Pineapple(Posted 2013) [#4]
How do the functions which return iterators such as MapKeys work, then? And the error isn't isolated to the ObjectEnumerator method, the error also occurs when trying to use NodeEnumerator, which is the one I was really expecting to use. And I've written similar code in the past that worked without issue.

This code executes without any error and runs as expected:

Import pine.HashTable

Local hash:HashTable=CreateHash(32)
HashInsert hash,"foo","bar"

For Local s$=EachIn hash.ObjectEnumerator()
	Print s
Next


And the pine.HashTable module is available here, for any relevant code: http://blitzbasic.com/Community/post.php?topic=97992&post=1141947

I'm only trying to reproduce the same basic thing that I did before, and I'm not sure what's different about the enumeration code.


Pineapple(Posted 2013) [#5]
Okay, I found the issue. It was a very easy fix.

I merely added this to my hash2denum type:

Method ObjectEnumerator:hash2denum()
	Return Self
End Method