Some notes
Alex Martelli
aleaxit at yahoo.com
Sat Oct 16 08:34:30 EDT 2004
Scott David Daniels <Scott.Daniels at Acm.Org> wrote:
> Alex Martelli wrote:
> > [lotsa stuff I like]
> >>>- The functional IF seems interesting, like:
> >>>if(cond, code1, code2) ... (Or ... a different syntax, [allowing elif])
> >>Many variants have been proposed over the years, but none have ever made
> >>it in.
> > I think generators could get us close to this kind of thing (in Py3k).
> >
> > They'd have to sprout a new method 'skip', similar to 'next' but defined
> > to not evaluate the argument of the next yield.
> That seems pretty tough to define. for a generator like:
> def agen():
> source = open('somedatafile.txt')
> for i in range(1000):
> source.seek(4 * i**2 + 33 * i + 52)
> line = source.readline()
> if line.startswith('magic:'):
> yield line[6:]
> source.close()
>
> What computation would "skip the evaluation of the next yield" avoid?
Just the 'line[6:]' slicing, for definiteness. I don't see anything
hard to define about it. Just conceptually turn each 'yield XXX' into:
if _must_skip_next_yield: yield None
else: yield XXX
with local flag _must_skip_next_yield being automatically set to False
when .next() is called on the iterator object, set to True when .skip()
is called.
> > ... Such functions as lisp's cond might then easily be implemented:
> >
> > def cond(@_args):
> > for test in _args:
> > if test: return _args.next()
> > else: _args.skip()
>
> what would be different between this and:
>
> > def cond(@_args):
> > for test in _args:
> > if test: return _args.next()
> > else: _args.next()
Your alternative evaluates every item in the _args iterator, and thus is
completely useless for cond's "guarding" purposes. E.g.,
inverse = cond(x, 1.0/x, True, None)
would raise a ZeroDivisionError under your alternative, would just set
inverse to None under my proposal.
> I just don't understand the semantics of .skip().
Maybe it was too obvious to me so I failed to specify it in detail.
An example iterator that just does selective evaluation in a sequence:
def someof(sequence):
for i in xrange(len(sequence)):
if _must_skip_next_yield: yield None
else: yield sequence[i]
with the same semantics for the special flag _must_skip_next_yield.
Alternatively, if a sequence's iterator also implemented skip:
def someof(iterable):
it = iter(iterable)
assert has_attr(it, 'skip')
while True:
if _must_skip_next_yield: yield it.skip()
else: yield it.next()
this would be essentially a "no-op" wrapper of iterable, essentially
identical to iter(iterable), and I'm just showing it to further
illustrate the intended semantics of 'skip'.
The iterator over arguments, which I propose, could not be implemented
in Python today (Python today has no way to collect yet-unevaluated
arguments). I do believe that the C interpreter would need few changes
to implement it (what syntax to use to signal it being the one
contentious part), and even fewer to accept a .skip method on generators
and use it to set a local variable _must_skip_next_yield in the
generator's frame (not particularly useful, I believe -- not all
iterators would have to be skippable, and, unless strong use cases
emerge, normal generators might well be deemed nonskippable ones).
Alex
More information about the Python-list
mailing list