oops, I forgot to force calls to  the inner function * definitions.  Another 
hazard of the plan of record that my alternative proposal doesn't have.  I 
fixed occurrence of this bug below:
On Sep 11, 2012, at 9:42 PM, Allen Wirfs-Brock wrote:

> 
> On Sep 11, 2012, at 7:48 PM, Jason Orendorff wrote:
> 
>> I'd appreciate a less contrived motivating example.  The best way to
>> implement this dataSnapshot() function is simply:
>> 
>>    function dataSnapshot(aCollection) {
>>        return aCollection.clone();
>>    }
>> 
>> -j
>> 
> 
> 
> My original example was something like:
> 
> function *dataSnapshot(aDataSource) {
>   let snapshot = aDataSource.captureCurrentState();
>   for (let i=0; i<snapshot.length; i++) yield snapshot[i]
> }
> 
> It wasn't actually quite as  intentionally clear as the above and that 
> allowed it to evolve within the thread into something that could arguably be 
> restated as you show. But that was why I created the original example.
> 
> The intent of the original was to show a situation where:
> 
> there is a dynamically changing data source you want to analyze
> You need to capture it for the analysis while it is in a stable state
> The data capture process does not produce a "clone" but a different (perhaps 
> more efficient for readonly access)
> You know how to navigate this captured data structure and want to provide a 
> generator-based iteration that a analysis process can you to access its 
> elements
> You need to be sure that the data is captured when at the exact point in 
> program where "dataSnapshot" was invoked, not at some arbietrary later time 
> when "next" is first called.
> 
> I think these requirements are pretty typical of a common situation that 
> occurs  when you want to perform stable traversal over dynamically mutable 
> object structures and the example was contrived to show some pitfalls that 
> could occur if you try to do this using a generator.
> 
> The original example fails for at least the last bullet.  To fix that, it 
> would have to be rewritten, something like:
> 
> function dataSnapshot(aDataSource) {
>   let snapshot = aDataSource.captureCurrentState();
>   return  function *() {
>      for (let i=0; i<snapshot.length; i++) yield snapshot[i]
>    }();   //<--- return generator instance, not the generator constructor
> }
> 
> Note that this rewrite eliminates the need for an formal parameters on the 
> actual generator definition.
> 
> If dataSnapshot was a method on some object and the iteration results 
> depended upon that object, you might have instead originally coded it as:
> 
> class DataSourceAnalyzer {
>     ...  //a constructor and other methods
>    *dataSnapshot(aDataSource) {
>       let snapshot = aDataSource.captureCurrentState();
>       for (let i=0; i<snapshot.length; i++) yield 
> this.analyzeElement(snapshot[i]);  //  <--- note use of this
>   }
> }
> 
> This also falls the last requirement in the bullet list above.  So, you might 
> refactor similarly to what I did for the non-method form:
> 
> class DataSourceAnalyzer {
>     ...  //a constructor and other methods
>    dataSnapshot(aDataSource) {
>       let snapshot = aDataSource.captureCurrentState();
>       return  function *() {
>          for (let i=0; i<snapshot.length; i++) yield 
> this.analyzeElement(snapshot[i]);  //  <--- note erroneous use of this
>       }();   //<--- return generator instance, not the generator constructor
>   }
> }
> 
> and forget that the function * expression uses a dynamic this.  If you 
> remembered that you would instead have had to revert to ES<6 style this 
> capture:
> 
> class DataSourceAnalyzer {
>     ...  //a constructor and other methods
>    dataSnapshot(aDataSource) {
>       let snapshot = aDataSource.captureCurrentState();
>       let self = this;
>       return  function *() {
>          for (let i=0; i<snapshot.length; i++) yield 
> self.analyzeElement(snapshot[i]);  //  <--- note use of self instead of this
>       }();   //<--- return generator instance, not the generator constructor
>   }
> }
> 
> Using my alternative generator syntax, this would be written as:
> 
> class DataSourceAnalyzer {
>     ...  //a constructor and other methods
>    dataSnapshot(aDataSource) {
>       let snapshot = aDataSource.captureCurrentState();
>       return  *=> for (let i=0; i<snapshot.length; i++) yield 
> this(snapshot[i]);  //  <--- note valid of lexical this
>   }
> }
> 
> 
> 
> 
> 
> 
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to