Proposal: generator#clone() and generator#goto()

# Salvador de la Puente González (10 years ago)

Just a little presentation before the proposal. I'm Salvador de la Puente González (you can call me Salva, please). I'm working for Telefonica I+D in Mozilla Firefox OS and I'm a front-end developer, you can know more about me in unoyunodiez.com and my github user is lodr

Now, these day I was thinking about a generator feature. I have a use case for a transpiler I'm developing: in the source language you have procedures much more like Linux processes. The language have a block sentence clone for cloning a procedure. After cloning, father procedure simply ignores the block while coned procedure execute sentences inside. Like an automatized pid = fork() if (pid != 0) { .... }.

Now I'm addressing this problem from a AST perspective, transpiling procedures to a special generators able to fall through their sentences until reaching a specific yield.

But I think it could be easier if I could do something like generator#clone() returning a new generator object. This new generator is paused of the same yield as the original one and have a new variable environment with a shallow copy of the original's variable environment. The variable environment's parent chain would be the same as the original one.

Notice this is not related with data preservation as most of the objects being used by original generator will be shared with the new one (although this could be addressed as well) but with execution state.

In the same way, to provide a complete control over execution state inside generators I would like to propose generator#goto(yieldLabel) that could allow the developer to transfer the execution cursor to a labeled yield sentence. The result of the yield sentence could be the extended with the label for that yield.

I know it does not suffice to be a cool feature but I think it could trigger very interesting uses cases and applications in backtracking or temper algorithms.

What do you think?

# Tab Atkins Jr. (10 years ago)

But I think it could be easier if I could do something like generator#clone() returning a new generator object.

Generators produce iterables, and you can just use a tee() function to "clone" an iterable. It's not hard to define yourself, and Python has a reference implementation: docs.python.org/2/library/itertools.html#itertools.tee

In the same way, to provide a complete control over execution state inside generators I would like to propose generator#goto(yieldLabel) that could allow the developer to transfer the execution cursor to a labeled yield sentence.

You can currently pass values back into the generator by passing an argument to .next(), and the generator can use that to do whatever it wishes, such as changing its internal state or jumping to a label.

# Salvador de la Puente González (10 years ago)

On 20 Aug 2014 17:39, "Tab Atkins Jr." <jackalmage at gmail.com> wrote:

Generators produce iterables, and you can just use a tee() function to "clone" an iterable. It's not hard to define yourself, and Python has a reference implementation: docs.python.org/2/library/itertools.html#itertools.tee

tee() function has two main problems. First and most important, it does not allow you to communicate different information by using send() on the new generators. The new generators, though independent, are actually tied to the state of the original iterator which leads to the second problem: the waste of space. You need to keep repeated values for each of the cloned generators.

My proposal performs only a shallow copy of the current state and most important, the execution state which allow you to send different information for the next iteration step. They are real independent generators.

You can currently pass values back into the generator by passing an argument to .next(), and the generator can use that to do whatever it wishes, such as changing its internal state or jumping to a label.

AFAIK, jumping to a label is not possible in ES5. You can only skip a labelled sentence. Indeed you can use the next information for changing the state. It's how I'm doing it right now but transpiling the functions this way is quite obscure.

I don't know if there are goto discussions in this list but it is one of my concerns, if JS is becoming something like the "high level target language of the web", to provide a powerful enough flow control sentence like goto.

I know the dangers behind this sentence and this is because I propose to limit its usage inside generators where scope is controlled and limited. You can not jump between functions and the jumping is controlled externally. The proposed goto() method does not send or advances the generator, it only changes the execution point. It can be completed with gen#yields() which would return all labels for labelled yields.

# John Lenz (10 years ago)

On Mon, Aug 25, 2014 at 2:17 AM, Salvador de la Puente González <salva at unoyunodiez.com> wrote:

AFAIK, jumping to a label is not possible in ES5. You can only skip a labelled sentence. Indeed you can use the next information for changing the state. It's how I'm doing it right now but transpiling the functions this way is quite obscure.

I don't know if there are goto discussions in this list but it is one of my concerns, if JS is becoming something like the "high level target language of the web", to provide a powerful enough flow control sentence like goto.

I know the dangers behind this sentence and this is because I propose to limit its usage inside generators where scope is controlled and limited. You can not jump between functions and the jumping is controlled externally. The proposed goto() method does not send or advances the generator, it only changes the execution point. It can be completed with gen#yields() which would return all labels for labelled yields.

Superficially, this sounds like a switch statement. I have a hard time envisioning something that is more powerful and doesn't cause lots of problems.

switch (start) {
  case 1:  yield something;
      // fall through
  case 2:  yield something;
}
# Salvador de la Puente González (10 years ago)

Thank you. Seems like I could use a switch inside a while (true) loop to make transpiling easier but it's quite hacked and it don't allow you to skip to jump from a case to another unless carefully added guards.

Don't you think goto() function is not safe enough? As I said, this is not for regular programming but for flow control when implementing transpilers for other languages.