Detecting if an iterator will be consumed
<p>Is there an uniform way of knowing if an iterable object will be consumed by the iteration?</p>

<p>Suppose you have a certain function <code>crunch</code> which asks for an iterable object for parameter, and uses it many times. Something like:</p>

<pre><code>def crunch (vals):

    for v in vals:
        chomp(v)

    for v in vals:
        yum(v)
</code></pre>

<p>(note: merging together the two <code>for</code> loops is not an option).</p>

<p>An issue arises if the function gets called with an iterable which is not a list. In the following call the <code>yum</code> function is never executed:</p>

<pre><code>crunch(iter(range(4))
</code></pre>

<p>We could in principle fix this by redefining the <code>crunch</code> function as follows:</p>

<pre><code>def crunch (vals):
    vals = list(vals)

    for v in vals:
        chomp(v)

    for v in vals:
        yum(v)
</code></pre>

<p>But this would result in using twice the memory if the call to <code>crunch</code> is:</p>

<pre><code>hugeList = list(longDataStream)
crunch(hugeList)
</code></pre>

<p>We could fix this by defining <code>crunch</code> like this:</p>

<pre><code>def crunch (vals):
    if type(vals) is not list:
        vals = list(vals)

    for v in vals:
        chomp(v)

    for v in vals:
        yum(v)
</code></pre>

<p>But still there colud be the case in which the calling code stores data in something which</p>

<ul>
<li>cannot be consumed</li>
<li>is not a list</li>
</ul>

<p>For instance:</p>

<pre><code>from collections import deque
hugeDeque = deque(longDataStream)
crunch(hugeDeque)
</code></pre>

<p>It would be nice to have a <code>isconsumable</code> predicate, so that we can define <code>crunch</code> like this:</p>

<pre><code>def crunch (vals):
    if isconsumable(vals):
        vals = list(vals)

    for v in vals:
        chomp(v)

    for v in vals:
        yum(v)
</code></pre>

<p>Is there a solution for this problem?</p>
