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

feat: use iterable object directly #113

Merged
merged 5 commits into from
May 19, 2024

Conversation

LviatYi
Copy link
Contributor

@LviatYi LviatYi commented May 19, 2024

BackGround

In C#, iterable objects can be iterated over using LINQ in the following way:

var list = users
  .Where(u => user.Name.Contains("Yi"))
  .Select(u => u.id);

Here, users is an object of type IEnumerable<T>, meaning it implements the IEnumerator interface.

IEnumerable | MSDN

In JS/Ts, a similar concept exists for iterables.
For example, Map is an iterable object that can be iterated by for...of because it implements the Iterable<T> interface (Ts), i.e., it contains a [Symbol.iterator] method.

Feature

This pull request enhances the from function by enabling it to accept Iterable<T> objects.

This PR aims to automatically invoke the [Symbol.iterator] method on objects that possess it to obtain an iterator, and then use this iterator to construct an Enumerable.

Key Changes

  • New:

      // Enumerable.from
      {
          // iterable object
          if (typeof Symbol !== 'undefined' && typeof obj[Symbol.iterator] !== 'undefined') {
              let iterator;
              return new Enumerable(function () {
                  return new IEnumerator(
                      function () {
                          iterator = obj[Symbol.iterator]()
                      },
                      function () {
                          var next = iterator.next();
                          return (next.done ? false : (this.yieldReturn(next.value)));
                      },
                      Functions.Blank);
              });
          }
      }
    • check if obj has a [Symbol.iterator] method. if ture, treat it as an iterable object.

Why

  • More Direct Usage: This change will accept iterable objects directly. For instance:

      const map = new Map();
    
      map.set(1, 2);
      map.set(2, 4);
    
      let result = Enumerable.from(map)
          .select(item => ({key: item[0], value: item[1]}))
          .select(item => item.key)
          .toArray();
    
      console.log(result);

    The above code will throw an error in 4.0.2 version because map is an iterable object, but linq treats it as an iterator and accesses its next function directly:

    Uncaught TypeError: obj.next is not a function
    

    In PR#110, an empty array is provided. The reason is that PR#110 expects an iterator rather than an iterable object. The following code will return the expected results:

      Enumerable.from(map[Symbol.iterator]())

This PR is more dangerous than last time. The last PR actually targeted a function signature that was not correctly aligned with linq.d.ts and corrected it to be fully compliant.
This PR adds a new feature, enabling the Enumerable.from function to accept parameters of type Iterable<T>. This is a completely new feature and may introduce new problems.

Thank you very much to the author for pointing out the problem of modifying irrelevant code. I will try to avoid this behavior in subsequent PRs.

This PR also reverts iterator.js:14-22 with changes from an unrelated commit.

@mihaifm mihaifm merged commit e469081 into mihaifm:master May 19, 2024
@mihaifm
Copy link
Owner

mihaifm commented May 19, 2024

Thanks. I released a new version with your fixes.

@LviatYi LviatYi deleted the feature/directUseIterable branch May 19, 2024 10:40
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

Successfully merging this pull request may close these issues.

2 participants