1

Help me wrap my head around this example:

function* genFuncWithReturn() {
    yield 'a';
    yield 'b';
    return 'The result';
}
function* logReturned(genObj) {
    const result = yield* genObj;
    console.log(result); // (A)
}

Results in:

> [...logReturned(genFuncWithReturn())]
The result
[ 'a', 'b' ]

So, my question is why and how result of return statement is produced first and recursive generator statement second?

  • 2
    `[...logReturned(...)]` produces a new array *after* `logReturned` terminated. And just *before* `logReturned` terminates, it calls `console.log(result)`. – Felix Kling Dec 20 '18 at 19:59
  • Felix King, so console.log(result) outputs only return statement while .. spread operator returns only yield statement results? – SomeGuyOhMy Dec 20 '18 at 20:00
  • It might be worth your while to write this code in a way that requires less mental gyrations. The person coming after you will have difficulty reasoning about such code. – Robert Harvey Dec 20 '18 at 20:01
  • [`...` is not an operator!](https://stackoverflow.com/questions/37151966/what-is-spreadelement-in-ecmascript-documentation-is-it-the-same-as-spread-oper/37152508#37152508), but yes. – Felix Kling Dec 20 '18 at 20:04

1 Answers1

3

[...logReturned(...)] produces a new array after logReturned terminated. And just before logReturned terminates, it calls console.log(result).

Maybe this ASCII art helps understand the flow:

┌──────────────────────┐     ┌──────────────────────┐      ┌─────────────────────┐
│[...logReturned(...)] │     │     logReturned      │      │  genFuncWithReturn  │
└──────────────────────┘     └──────────────────────┘      └─────────────────────┘
            │                            │                            │           
            │                            │                            │           
            │   get next from iterator   │                            │           
            │ ─────────────────────────▶ │   get next from iterator   │           
            │                            │ ─────────────────────────▶ │           
            │                            │                            │           
            │                            │         yield 'a'          │           
            │          yield 'a'         │ ◀───────────────────────── │           
            │ ◀───────────────────────── │                            │           
            │                            │                            │           
     (remembers 'a')                     │                            │           
            │                            │                            │           
            │    get next from iterator  │                            │           
            │ ─────────────────────────▶ │   get next from iterator   │           
            │                            │ ─────────────────────────▶ │           
            │                            │                            │           
            │                            │         yield 'b'          │           
            │          yield 'b'         │ ◀───────────────────────── │           
            │ ◀───────────────────────── │                            │           
            │                            │                            │           
     (remembers 'b')                     │                            │           
            │                            │                            │           
            │  get next from iterator    │                            │           
            │ ─────────────────────────▶ │   get next from iterator   │           
            │                            │ ─────────────────────────▶ │           
            │                            │                            │           
            │                            │  done, return 'The result' │           
            │                            │ ◀───────────────────────── │           
            │                            │                            │           
            │                    console.log(result)             (terminates)     
            │                            │                                        
            │            done            │                                        
   return   │ ◀───────────────────────── │                                        
 ['a', 'b'] │                            │                                        
◀───────────│                      (terminates)                                   
            │                                                                     
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143