# Iterable protocol and observable

**URL:** <https://talk.observablehq.com/t/iterable-protocol-and-observable/736>\
**Category:** Help\
**Created:** [May 9, 2018, 3:33pm UTC](https://talk.observablehq.com/t/iterable-protocol-and-observable/736 "2018-05-09T15:33:07Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mpj](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mpj/32/3540_2.png) [@mpj](https://talk.observablehq.com/u/mpj)\
**Post date:** [May 9, 2018, 3:33pm UTC](https://talk.observablehq.com/t/iterable-protocol-and-observable/736/1 "2018-05-09T15:33:07Z")

</div>

I’m trying to create a custom iterable, and I’m trying to return it in a way that Observable recognises it, but I cannot figure out how to make it work. Writing this little wrapper works, but I’d like Observable to recognise the object returned from customIterable as an Iterable automatically, is that possible?

```javascript
{
  const customIterable = () => ({
    [Symbol.asyncIterator]: function() {
      let i = 0
      return {

        next: function() {
          i++
          return delay(1).then(() => ({
            value: i,
            done: false
          }))
        }
      }
    }
  })
  
  const iterator = customIterable()[Symbol.asyncIterator]()
  while (true) {
    const {done, value} = await iterator.next();
    if (done) return;
    yield value;
  }
  
}

```

It seeeeems like it should be possible, because if I do this:

```javascript
async function* t() {
  await delay(1)
  yield 1
  await delay(1)
  yield 2
  await delay(1)
  yield 3
}

```

and then just call

```javascript
t()

```

From a cell, it properly iterates the values. What is the difference between what t() returns and what customIterable() returns that make Observable recognise the other?

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [May 9, 2018, 4:35pm UTC](https://talk.observablehq.com/t/iterable-protocol-and-observable/736/2 "2018-05-09T16:35:37Z")

</div>

You need to return a “generatorish” object rather than an iterable; specifically, Observable looks for the _generator_.next and _generator_.return functions to test whether a cell is a generator. Here’s a new notebook on custom generators and iterables:

> **[Custom Generators](https://observablehq.com/@mbostock/custom-generators)**
>
> An Observable notebook by Mike Bostock.

---

<div class="post-metadata">

**Author:** ![mpj](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mpj/32/3540_2.png) [@mpj](https://talk.observablehq.com/u/mpj)\
**Post date:** [May 11, 2018, 9:49am UTC](https://talk.observablehq.com/t/iterable-protocol-and-observable/736/3 "2018-05-11T09:49:32Z")

</div>

> [@mbostock](#):
>
> You need to return a “generatorish” object rather than an iterable; specifically, Observable looks for the _generator_ .next and _generator_ .return functions to test whether a cell is a generator. Here’s a new notebook on custom generators and iterables:

Thank you, thats solves my problem!

Out of curiosity, why does it need to be generatorish and not just an iterator? What is the return method used for?

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [May 11, 2018, 4:03pm UTC](https://talk.observablehq.com/t/iterable-protocol-and-observable/736/4 "2018-05-11T16:03:21Z")

</div>

If we interpreted any iterable as a value that changes over time (rather than restricting this interpretation to generators), there would be many false positives: cases where you intended the value of the cell to be an iterable object, but instead Observable pulled values iteratively. In particular, Array, Map, Set and other common collections in JavaScript are iterable. So if we allowed any iterable and you said:

```auto
x = [0, 1, 2, 3, 4, 5, …]

```

The value of _x_ as seen from other cells would not be the array; it’d first be 0, then 1, then 2, sixty times a second. It would be as if there were an implicit [yield-star](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/yield*):

```auto
x = yield* [0, 1, 2, 3, 4, 5, …]

```

Generators are less common that iterables, so it was convenient to limit the special interpretation to this more specific type. Also, you can easily adapt any iterable to a generator through yield-star, providing an opt-in interpretation if desired.

Also, like an iterator but _not_ necessarily an iterable, reading a generator is inherently destructive (read-once). Multiple cells reading directly from a single generator using [_generator_.next](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Generator/next) would be non-deterministic, and you generally want to avoid side-effects in Observable. Making generator the representation of a value over time affords more deterministic behavior.

Note that reading an iterator is also destructive, and even an iterable is sometimes: many iterators implement iterable (the [Symbol.iterator] method) by returning itself! For example, a Map can be iterated many times, but the return value of _map_.values can only be iterated once; you have to call _map_.values each time you want to iterate. But the common types are pure, and you can always splat a destructive iterable like _map_.values into an array using the spread operator:

```auto
[...map.values()]

```

To answer the other question, [_generator_.return](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) allows generators (and generator cells) to clean up after themselves. You can read about that here:

> **[Invalidation](https://observablehq.com/@mbostock/disposing-content)**
>
> An Observable notebook.

Also, in case anyone reading hasn’t seen it yet, here is the introduction to generators:

> **[Introduction to Generators](https://observablehq.com/@mbostock/introduction-to-generators)**
>
> An Observable notebook.
