[Python-ideas] Fwd: quantifications, and tuple patterns

Paul Moore p.f.moore at gmail.com
Sun Jan 15 20:46:38 CET 2012


On 15 January 2012 17:01, Annie Liu <liu at cs.stonybrook.edu> wrote:
>   It is win-win-win to do, because they help
>   . make programming easier
>   . make programs clearer
>   . make programs more efficient
>   This is a dream situation, considering the usual conflicts among these!

Hmm, while I'm coming to like the concept, I still think that
"clearer" might be a bit strong. For simple uses where all() and any()
work as replacements, those builtins are already pretty clear. For
cases where they won't do, then quantifiers as you propose are
certainly no worse than some of the other proposed alternatives, but
I'm not sure how much better they are, either. But never mind, clarity
is a matter of perspective at best :-)

>  > I think that's why the (otherwise odd) "while there are any, pick one"
>  > construct is used. Of course, for an algorithm like that, I'd
>  > probably tend to choose a different data structure, maybe something
>  > like a work queue.
>
> In fact, "while some x in s" is exactly a best way to write a work
> list algorithm, where either a queue or stack could be used (in graph
> algorithms, a queue corresponds to breadth-first-search, and a stack
> corresponds to depth-first-search), but when the order of picking
> elements doesn't matter, "while some x in s" is easier and clearer.

Yes, I see your point here - in this case "while some x in s" reads
nicely, and does what I'd expect.

> I feel that "has" reads well for single quantification, but not as
> well for nested (though "if" sounds a bit weird also, and I'd really
> like to use "|" if it doesn't break Python rules :-)).  Compare:
>
>   each x in s has (some y in t has pred)
>
>   each x in s if (some y in t if pred)
>
>   each x in s | (some y in t | pred)
>
> BTW, functions "all" and "any" are much harder to read here:
>
>   all(any(pred for y in t) for x in s)
>
> and it is even harder when you have some real contents for pred, s,
> and t, not just the template here.

OK, I'm willing to concede that the all/any formulation isn't as
"clean looking" as the alternatives you propose. But I did understand
it instantly, whereas I found that I couldn't work out the meaning of
your form straight off, but had to "cheat" by looking at the all/any
formulation, and work back from that. How much of that is simply
because I'm more familiar with the conventional form, I'm not sure
(it's certainly a reasonably substantial part of it - and if each/some
become part of the language, they will become familiar too).

But what I want to do is break things down into individual constructs
- that's how my mind works (so sue me! :-)) With the all/any form, it
goes:

   all(...) - function call, with a generator expression as argument
   ... for x in s - generator expression, argument to all
   any(...) - function call again
   pred for y in t - generator expression

So we have 2 fundamental constructs, both used in many contexts
throughout Python, and hence both familiar, combined in simple ways.

For your each/some formulation we have:

   each x in s has ... - a new type of construct, and each expression
   some y in t has pred - another new type of construct, a some expression

each and some expressions feel like they have structure in common with
generator expressions, but they look slightly different. Actually,
isn't it true that "each x in s has pred" is basically "all(x for x in
s if pred)" except that no witness is captured? So syntactically the
differences are:

   - you avoid the repetition of "x for x" (which is a known wart of
generator expressions)
   - you're using has instead of if (it reads better, but otherwise is
a bit of a spurious difference - you did propose if as an alternative)
   - you avoid the parentheses

There are some subtler differences (you use "pred for x..." in the
all/any version, whereas I'm equating each/some forms with "x for x"
variations, for example). But basically this is my real concern - your
proposed constructs are special case syntax that is close to, but
subtly different from, existing forms. That "nearly but not quite the
same" aspect is where I have concerns about readability (and
teachability).

The problem is that each/some can't build on generators, because if
they do you need to explicitly specify the variable to use to capture
the witness. And then if you use a generator expression, you end up
with something like "some VAR GENERATOR", which becomes a monstrosity
like "some x (x for x in ...)". So they have to build on generator
*expressions* which are a subset of general generators. And we get to
special case synax straight off. The advantage of any/all is that they
work on any generator - whether it's a generator expression or some
other form of generator).

> In summary, again, I think we should support proper quantifications.

I'm getting more comfortable with the idea, but I think it needs a bit
more discussion to come up with something that fits in cleanly with
the rest of Python, while still adding the value you want.

Paul.



More information about the Python-ideas mailing list