Hi Tomsy,

Thanks for the question. I thought some about how best to answer your
question and explain an iterator.


A couple of points here are:

1) You call fibonacci in the loop body and not as part of the
    for-loop statement (in the iterable-expression).

2) The iterator you define will start from the beginning each time
    it is invoked inside the loop body. Consider the following with
    a write statement in the iterator:

    iter fibonacci(n : int)
    {
    var current,next:int;
    write(" 'Iterator begins' ");  // executes when iterator begins execution
    if(n==1) then (current,next)=(0,1);
    yield current;
    (current,next)=(next,current+next);
    }
    for i in 1..10 do writeln("Fib(",i,") = ",fibonacci(i));

    ======= output ======

    Fib(1) =  'Iterator begins' 0
    Fib(2) =  'Iterator begins' 0
    Fib(3) =  'Iterator begins' 0
    Fib(4) =  'Iterator begins' 0
    Fib(5) =  'Iterator begins' 0
    Fib(6) =  'Iterator begins' 0
    Fib(7) =  'Iterator begins' 0
    Fib(8) =  'Iterator begins' 0
    Fib(9) =  'Iterator begins' 0
    Fib(10) =  'Iterator begins' 0

    You can see that the iterator starts executing from the beginning
    for each iteration of the for-loop. Therefore, current is always 0.


Consider the following example with an unrolled iteration loop
and the iterator is invoked within the iterable-expression:

   iter fibonacci()
   {
     var current,next:int;
     var n = 1;
     write(" 'Iterator begins' ");
     if(n==1) then (current,next)=(1,1);
     write(" 'yield 0' ");
     yield current;
     n += 1;
     (current,next)=(next,current+next);
     write(" 'yield 1' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 2' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 3' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 4' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 5' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 6' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 7' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 8' ");
     yield current;
     (current,next)=(next,current+next);
     write(" 'yield 9' ");
     yield current;
     (current,next)=(next,current+next);
   }

   // fibonacci called within the iterable expression
   // zippered iteration used
   for (i,f) in zip(1..10, fibonacci()) do writeln("Fib(",i,") = ", f);

   ===== output =====

  'Iterator begins'  'yield 0' Fib(1) = 1
  'yield 1' Fib(2) = 1
  'yield 2' Fib(3) = 2
  'yield 3' Fib(4) = 3
  'yield 4' Fib(5) = 5
  'yield 5' Fib(6) = 8
  'yield 6' Fib(7) = 13
  'yield 7' Fib(8) = 21
  'yield 8' Fib(9) = 34
  'yield 9' Fib(10) = 55

Notice that each write statement only executes once, but different
write statements execute during different iterations of the loop.
Therefore, a different 'yield' statement is returning values each
time.

The example above, is hard wired to yield exactly 10 values (as there are
exactly 10 yield statements). In order to generalize the above iterator,
a loop is needed:

   iter fibonacci(n:int)  // accepts an argument
   {
     var current,next:int;
     write(" 'Iterator begins' ");
     (current,next)=(1,1);

     // will yield n values
     for i in 1..n {
       write(" 'yield ", i, "' ");
       yield current;                // execution stops here
       // execution begins here the next time
       (current,next)=(next,current+next);
     }
   }

   for (i,f) in zip(1..10, fibonacci(10)) do writeln("Fib(",i,") = ", f);

   ===== output =====

    'Iterator begins'  'yield 1' Fib(1) = 1
  'yield 2' Fib(2) = 1
  'yield 3' Fib(3) = 2
  'yield 4' Fib(4) = 3
  'yield 5' Fib(5) = 5
  'yield 6' Fib(6) = 8
  'yield 7' Fib(7) = 13
  'yield 8' Fib(8) = 21
  'yield 9' Fib(9) = 34
  'yield 10' Fib(10) = 55

This produces the same output but is general enough to work with
more than 10 iterations (thus the value 10 is passed as an argument
to fibonacci).


Please let me know if any of this is not clear. I hope it helps.

Tom MacDonald

On Thu, 19 Nov 2015, Tomsy Paul wrote:
> 
> 
> Hello all,
> 
> I was going through test/release/examples/primers/iterators.chpl
> In the comments of Fibonacci, it is said that
> 
> // The first time, this iterator is run, it proceeds this far
> .
> .
> // The next time it is called, execution resumes here
> 
> The term call is confusing to me. The iterator takes only one execution, I
> mean entry to the iterator happens only once, isn't it?
> 
> Consider the following code
> 
> iter fibonacci(n : int)
> {
> var current,next:int;
> if(n==1) then (current,next)=(0,1);
> yield current;
> (current,next)=(next,current+next);
> }
> for i in 1..10 do writeln("Fib(",i,") = ",fibonacci(i));
> 
> The output is fib(0) for all values of i. Could you please explain.

------------------------------------------------------------------------------
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users

Reply via email to