Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The code shows how you can generate an arbitrary sequence of numbers<br> by means of <em>'generators'</em>. </p> <p><em>generators</em> are a popular tool in dynamic languages like python and enable one to<br> iterate over an arbitrary long sequence without allocating the whole sequence at once. </p> <p>The <em>tracking</em> happens in the lines</p> <pre><code>p-&gt;next = pow2next; p-&gt;continue_from = 0; </code></pre> <p>Which tells <strong><em>p</em></strong> that it should call <strong><em>pow2next</em></strong> to obtain the next item in the sequence<br> and <strong><em>continue_from = 0</em></strong> to indicate that where at the start of the sequence.</p> <p>When you call <strong><em>p->next(p)</em></strong> it will in fact just call <strong><em>pow2next</em></strong> with <strong><em>p</em></strong> as it's parameter. For the first call this will simply return <strong>1</strong> and increment <em>continue_from</em> to <strong>2</strong>.</p> <pre><code>switch(p-&gt;continue_from) { case 0: p-&gt;continue_from = 1; return 1; /* ... */ </code></pre> <p>On the second call (<strong><em>continue_from = 2</em></strong>) it will create a new <strong><em>map_gen</em></strong> structure working on a fresh <em>struct</em> <strong><em>pow2s</em></strong> and using the function <strong><em>times2</em></strong>:</p> <pre><code>case 1: p-&gt;g = map(times2,pow2()) ; p-&gt;continue_from = 2; return p-&gt;g-&gt;next(p-&gt;g) ; /* ... */ </code></pre> <p>All further calls go through <strong><em>p->g->next(p->g)</em></strong> which uses <strong><em>times2</em></strong> and <strong><em>map_gen</em></strong> to retrieve the next value / create new <strong><em>map_gen</em></strong> structures as needed. All value tracking is done using the struct-member <strong><em>continue_from</em></strong> or by using return codes.</p> <p>While showing an interesting approach to generators in C I have to state that this code leaks memory! As you can see it allocates new structures using <strong><em>malloc</em></strong> but it never <strong><em>free</em></strong>'s them.</p> <p>I hope this explanation is not to confusing even if you're just starting to learn C.<br> If you really want to understand generators you may like to have a little python ex-course ;)</p> <p><strong>UPDATE</strong></p> <p>As you stated in your comment <em>none of the generators ever seems to return a value > 2</em>.<br> The key to the increasing numbers lies in the function <em>map_next</em>:</p> <pre><code>int map_next(struct mapgen *p) { return p-&gt;f(p-&gt;g-&gt;next(p-&gt;g)); } </code></pre> <p>What this does is, instead of returning a fix, number it applies <strong><em>p->f()</em></strong><br> (in our case the function <strong><em>times2()</em></strong> to the result of <strong><em>p->g->next(p->g)</em></strong>.</p> <p>This is a recursive call. </p> <p>It will continue to call <strong><em>map_next()</em></strong> on each <strong><em>map_gen</em></strong> in the list until it reaches the last one.<br> This last element will return a fix value (either <strong>1</strong> or <strong>2</strong>).<br> Which is then passed back to the previous call which will apply <strong><em>times2()</em></strong> on it and return the result to it's caller, which in turn will apply <strong><em>times2()</em></strong> on it and return the result to it's caller.... (you get the idea). </p> <p>All these recursive calls sum up and form the final value.<br> If you print out the result of each <strong><em>pow2next()</em></strong> call you will get this: </p> <pre><code>/* first call */ 1 pow2next: returning 1 pow2next: returning 2 /* times2(1) */ 2 pow2next: returning 1 pow2next: returning 2 /* times2(1) */ pow2next: returning 4 /* times2(2) */ 4 pow2next: returning 1 pow2next: returning 2 /* times2(1) */ pow2next: returning 4 /* times2(2) */ pow2next: returning 8 /* times2(4) */ 8 pow2next: returning 1 pow2next: returning 2 /* times2(1) */ pow2next: returning 4 /* times2(2) */ pow2next: returning 8 /* times2(4) */ pow2next: returning 16 /* times2(8) */ 16 /* and so on */ </code></pre> <p>You can see clearly how the result of the top most call is passed all the way back to the first call to form the result. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload