On 8 May 2018 at 04:19, Brett Cannon <brett@python.org> wrote:
My brain wants to drop the variable name in front of 'given':

if given m = pattern.search(data):

while given m = pattern.search(remaining_data):

Maybe it's because the examples use such a short variable name?

Does that change if the condition isn't just "bool(name)"? For example:

    if y > 0 given y = f(x):
        ...

That's the situation where I strongly prefer the postfix operator spelling, since it's pretty clear how I should pronounce it (i.e. "if y is greater than zero, given y is set to f-of-x, then ..."). By contrast, while a variety of  plausible suggestions have been made, I still don't really know how to pronounce "if (y := f(x)) > 0:)" in a way that's going to be clear to an English-speaking listener (aside from pronouncing it the same way as I'd pronounce the version using "given", but that then raises the question of "Why isn't it written the way it is pronounced?").

I do agree with Tim that the name repetition would strongly encourage the use of short names rather than long ones (since you're always typing them at least twice), such that we'd probably see code like:

    while not probable_prime(n) given (n =
                            highbit | randrange(1, highbit, 2)):
        pass

Rather than the more explicit:

    while not probable_prime(candidate) given (candidate =
                            highbit | randrange(1, highbit, 2)):
        pass

However, I'd still consider both of those easier to follow than:

    while not probable_prime(candidate := highbit | randrange(1, highbit, 2)):
        pass

since it's really unclear to me that "candidate" in the latter form is a positional argument being bound to a name in the local environment, and *not* a keyword argument being passed to "probable_prime".

I've also been pondering what the given variant might look like as a generally available postfix operator, rather than being restricted to if/elif/while clauses, and I think that would have interesting implications for the flexibility of its usage in comprehensions, since there would now be *three* places where "given" could appear (as is already the case for the inline binding operator spelling):

- in the result expression
- in the iterable expression
- in the filter expression

That is:

    [(x, y, x - y) given y = f(x) for x in data]
    [(x, data) for x in data given data = get_data()]
    [(x, y, x/y) for x in data if y given y = f(x)]

Rather than:

    [(x, y := f(x), x - y) for x in data]
    [(x, data) for x in data := get_data()]
    [(x, y, x/y) for x in data if y := f(x)]

Opening it up that way would allow for some odd usages that might need to be discouraged in PEP 8 (like explicitly preferring "probable_prime(n) given n = highbit | randrange(1, highbit, 2)" to "probable_prime(n given n = highbit | randrange(1, highbit, 2))"), but it would probably still be simpler overall than attempting to restrict the construct purely to if/elif/while.

Even as a generally available postfix keyword, "given" should still be amenable to the treatment where it could be allowed as a variable name in a non-operator context (since we don't allow two adjacent expressions to imply a function call, it's only prefix keywords that have to be disallowed as names to avoid ambiguity in the parser).

Cheers,
Nick.

--
Nick Coghlan   |   ncoghlan@gmail.com   |   Brisbane, Australia