# [Python-ideas] Statements vs Expressions... why?

Cliff Wells cliff at develix.com
Sun Sep 14 10:25:18 CEST 2008

```On Sun, 2008-09-14 at 08:36 +0100, Arnaud Delobelle wrote:
> On 14 Sep 2008, at 07:36, Cliff Wells wrote:
>
> > On Sun, 2008-09-14 at 07:23 +0100, Arnaud Delobelle wrote:
> >> On 13 Sep 2008, at 23:17, Cliff Wells wrote:
> >>
> >>> On Sat, 2008-09-13 at 19:01 +0100, Arnaud Delobelle wrote:
> >>>>
> >>>> So what does:
> >>>>
> >>>> a = (if False: 1)
> >>>>
> >>>> evaluate to?
> >>>
> >>> That's a good question.  This is one of those areas where a
> >>> definition
> >>> would need to be created.  My inclination is to say None (much
> >>> like a
> >>> function with no return statement).
> >>>
> >>
> >> Assuming the return value of "None", I go back to an example I gave
> >> earlier:
> >>
> >>    factors = for x in range(2, n):
> >>        if n % x == 0:
> >>            x
> >>
> >> This doesn't work as intended (filtering out the non-factors).  How
> >> to
> >> make it work?  The only way I can think of is to make (if 0: 1)
> >> return
> >> a special "non-value" which loops will then filter out.  But then we
> >> all know what happens to non-values.
> >>
> >> So how would you solve this problem?
> >
> > By writing it properly ;-)
> >
> > factors = for x in range ( 2, n ):
> >    if n % x == 0:
> >        yield x
> >
> > As I mentioned previously, in order to merge the concept of generator
> > with a for-expression would require bringing in the yield keyword,
> > just
> > as it does now for generator functions.
> >
> > The example you gave would evaluate to None (or perhaps an empty
> > list or
> > generator - that's a detail that would take more consideration before
> > defining it).
> >
>
> OK, but this seems to me incompatible with current Python:
>
> def chain(I, J):
>      for i in I: yield i
>      for j in J: yield j
>
> Currently
>
>  >>> '-'.join(chain('spam', 'eggs'))
> 's-p-a-m-e-g-g-s'
>
> With your proposal, the first *expression* (for i in I: yield i) will
> evaluate to something like iter(I) and then be discarded.  Then the
> second *expression* (for j in J: yield j) will evaluate to something
> like iter(J) which will be discarded.  So chain('spam', 'eggs') will
> return None.

It seems you have me on this one.  There's clearly other ways to do the
same thing, but since backwards-compatibility is a prerequisite I'll
have to concede the point.

A potential solution would to be to use a different keyword than "yield"
to separate current syntax from my proposed syntax (that is, distinguish
expression-scoped yield from function-scoped yield), and just side-step
the issue, but that seems unappealing to me.

Regards,
Cliff

```