Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior in [Symbol.iterator] #109

Closed
LviatYi opened this issue May 9, 2024 · 1 comment
Closed

Unexpected behavior in [Symbol.iterator] #109

LviatYi opened this issue May 9, 2024 · 1 comment

Comments

@LviatYi
Copy link
Contributor

LviatYi commented May 9, 2024

I have a type that implements [Symbol.iterator]:

class IteratorTest {
    // This is just a simple replacement for the data structure that needs to be traversed.
    // It may actually be a tree or other data structure implemented by a custom traversal.
    nums: number[] = [1, 2, 3, 4, 5];

    public [Symbol.iterator](): Iterator<number> {
        let idx = 0;
        return {
            next: (): IteratorResult<number> => {
                if (idx < this.nums.length) {
                    return {
                        value: this.nums[idx++],
                        done: false,
                    };
                } else return {
                    value: undefined,
                    done: true,
                };
            },
        };
    }
}

Enumerable returns an empty array when I try to use it like this:

// in linq.d.ts   export function from<T>(obj: Iterator<T>): IEnumerable<T>;
// so I called:
Enumerable.from(et[Symbol.iterator]()).toArray()

The reason is that during the construction of Enumerable.from():

// linq.js
    if (typeof obj != Types.Function) {
        // array or array-like object
        if (typeof obj.length == Types.Number) {
            return new ArrayEnumerable(obj);
        }

        // iterable object
        if (typeof Symbol !== 'undefined' && typeof obj[Symbol.iterator] !== 'undefined') { // use obj as who has [Symbol.iterator]
            return new Enumerable(function () {
                return new IEnumerator(
                    Functions.Blank,
                    function () {
                        var next = obj.next(); // use obj as iterator
                        return (next.done ? false : (this.yieldReturn(next.value)));
                    },
                    Functions.Blank);
            });
        }
    }

I'm not a typescript expert, but I think this code is dealing with Iterator. obj itself is an Iterator, but here we still try to access obj.[Symbol.iterator].
Then it tries to access obj.next() in the iteration, which is no problem because obj as an Iterator contains a next function.

So I had to change my code to this to get it to work properly:

class ETest {
    nums: number[] = [1, 2, 3, 4, 5];

    public [Symbol.iterator](): Iterator<number> {
        let idx = 0;
        return {
            next: (): IteratorResult<number> => {
                if (idx < this.nums.length) {
                    return {
                        value: this.nums[idx++],
                        done: false,
                    };
                } else return {
                    value: undefined,
                    done: true,
                };
            },

            // A useless function just to pass the `typeof obj[Symbol.iterator] !== 'undefined'` predicate
            [Symbol.iterator](): Iterator<number> {
                return {
                    next(...args): IteratorResult<number, any> {
                        return undefined;
                    },
                };
            },
        };
    }
}

Is there anything wrong with my usage? In my opinion, the former should be the correct usage of from<T>(obj: Iterator<T>): IEnumerable<T>

@mihaifm
Copy link
Owner

mihaifm commented May 19, 2024

Resolved in version 4.0.3

@mihaifm mihaifm closed this as completed May 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants