_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
Sorry, but these examples don't look as good examples for inline
assignments to me. I think that all these cases can be written better
without using the inline assignment.
> 1. Making an "exactly one branch is executed" construct clearer than is
> the case for nested if statements:
>
> if m := pattern.search(data):
> ...
> elif m := other_pattern.search(data):
> ...
> else:
> ...
This case can be better handled by combining patterns in a single
regular expression.
pattern = re.compile('(?P<foo>pattern1)|(?P<bar>pattern2)|...')
m = pattern.search(data)
if not m: # this can be omitted if the pattern is always found
...
elif m.group('foo'):
...
elif m.group('bar'):
...
See for example gettext.py where this pattern is used.
> 2. Replacing a loop-and-a-half construct:
>
> while m := pattern.search(remaining_data):
> ...
This case can be better handled by re.finditer().
for m in pattern.finditer(remaining_data):
...
In more complex cases it is handy to write a simple generator function
and iterate its result.
The large number of similar cases are covered by a two-argument iter().
> 3. Sharing values between filtering clauses and result expressions in
> comprehensions:
>
> result = [(x, y, x/y) for x in data if (y := f(x))]
There are a lot of ways of writing this. PEP 572 mentions them.
Different ways are used in real code depending on preferences of the
author. Actually the number of these cases is pretty low in comparison
with the total number of comprehensions.
It is possible to express an assignment in comprehensions with the "for
var in [value]" idiom, and this idiom is more powerful than PEP 572 in
this case because it allows to perform an assignment before the first
'for'. But really complex comprehensions could be better written as
'for' statements with explicit adding to the collection or yielding.
[Nick Coghlan <ncog...@gmail.com>]
> ...
> Using a new keyword (rather than a symbol) would make the new construct
> easier to identify and search for, but also comes with all the downsides of
> introducing a new keyword.
That deserves more thought. I started my paying career working on a
Fortran compiler, a language which, by design, had no reserved words
(although plenty of keywords). The language itself (and
vendor-specific extensions) never had to suffer "but adding a new
keyword could break old code!" consequences.
In practice that worked out very well, Yes, you _could_ write
hard-to-read code using language keywords as, e.g., identifier names
too, but, no, absolutely nobody did that outside of "stupid Fortran
tricks" posts on Usenet ;-) It had the _intended_ effect in practice:
no breakage of old code just because the language grew new
constructs.
It's no longer the case that Python avoided that entirely, since
"async def", "async for", and "async with" statements were added
_without_ making "async" a new reserved word. It may require pain in
the parser, but it's often doable anyway. At this stage in Python's
life, adding new _reserved_ words "should be" an extremely high bar -
but adding new non-reserved keywords (like "async") should be a much
lower bar.
That said, I expect it's easier in general to add a non-reserved
keyword introducing a statement (like "async") than one buried inside
expressions ("given").
I also note that Google seems to be getting smarter about non-alphabetic searches -- I just searched for "python << operator" and the first hit was https://wiki.python.org/moin/BitwiseOperators
recently I have discovered interesting fact: it seems one
can already use 'inline assignment' with current syntax. E.g.:
if exec("m = input()") or m:
print (m)
It seem to work as inline assignment correctly.
Yes it is just coincidence, BUT: this has the wanted effect!
- hides one line in "if" and "while"
- leaves the assignment statement (or is it expression now? ;)
- has explicit appearance
So we have it already?
At end you can convert the source of the whole script to a string
literal and write the whole script in one line. The problem solved!
[Nick Coghlan <ncog...@gmail.com>]
> ...
> The essence of the given clause concept would be to modify *these specific
> cases* (at least initially) to allow the condition expression to be followed
> by an inline assignment, of the form "given TARGET = EXPR".
I'm not clear on what "these specific cases" are, specifically ;-)
Conditions in "if", "elif", and "while" statement expressions?
Restricted to one "given" clause, or can they chain? In a listcomp,
is it one "given" clause per "if", or after at most one "if"? Or is
an "if" even needed at all in a listcomp? For example,
[(f(x)**2, f(x)**3) for x in xs]
has no conditions, and
[(fx := f(x))**2, fx**3) for x in xs]
is one reasonable use for binding expressions.
[(fx**2, fx**3) for x in xs given fx = f(x)]
reads better, although it's initially surprising (to my eyes) to find
fx defined "at the end". But no more surprising than the current:
[(fx**2, fx**3) for x in xs for fx in [f(x)]]
trick.
It''s certain sanest as
if x**2 + y**2 > 9 given x, y = func_returning_twople():
"given" really shines there!
The one-letter variable name obscures that it doesn't
actually reduce _redundancy_, though. That is, in the current
match = pattern.search(data)
if match:
it's obviously less redundant typing as:
if match := pattern.search(data):
In
if match given match = pattern.search(data):
the annoying visual redundancy (& typing) persists.
One more, a lovely (to my eyes) binding expression simplification
requiring two bindings in an `if` test, taken from real-life code I
happened to write during the PEP discussion:
diff = x - x_base
if diff:
g = gcd(diff, n)
if g > 1:
return g
collapsed to the crisp & clear:
if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
return g
If only one trailing "given" clause can be given per `if` test
expression, presumably I couldn't do that without trickery.
If it's
more general,
if (diff given diff = x _ xbase) and g > 1 given g = gcd(diff, n):
reads worse to my eyes (perhaps because of the "visual redundancy"
thing again), while
if diff and g > 1 given diff = x - x_base given g = gcd(diff, n):
has my eyes darting all over the place, and wondering which of the
trailing `given` clauses executes first.
(Note: Guido's already told me off-list that he doesn't like the way this spelling reads, but I wanted to share it anyway since it addresses one of the recurring requests in the PEP 572 discussions for a more targeted proposal that focused specifically on the use cases that folks had agreed were reasonable potential use cases for inline assignment expressions.I'll also note that another potential concern with this specific proposal is that even though "given" wasn't used as a term in any easily discovered Python APIs back when I first wrote PEP 3150, it's now part of the Hypothesis testing API, so adopting it as a keyword now would be markedly more disruptive than it might have been historically)
On 4 May 2018 at 22:06, Nick Coghlan <ncog...@gmail.com> wrote:(Note: Guido's already told me off-list that he doesn't like the way this spelling reads, but I wanted to share it anyway since it addresses one of the recurring requests in the PEP 572 discussions for a more targeted proposal that focused specifically on the use cases that folks had agreed were reasonable potential use cases for inline assignment expressions.I'll also note that another potential concern with this specific proposal is that even though "given" wasn't used as a term in any easily discovered Python APIs back when I first wrote PEP 3150, it's now part of the Hypothesis testing API, so adopting it as a keyword now would be markedly more disruptive than it might have been historically)Since I genuinely don't think this idea is important enough to disrupt hypothesis's public API, I've been pondering potential synonyms that are less likely to be common in real world code, while still being comprehensible and useful mnemonics for the proposed functionality.
Cheers,Constraining the syntax that way (at least initially) would avoid poking into any dark corners of Python's current scoping and expression execution ordering semantics, while still leaving the door open to later making "result given NAME = expr" a general purpose ternary operator that returns the LHS, while binding the RHS to the given name as a side effect.Using a new keyword (rather than a symbol) would make the new construct easier to identify and search for, but also comes with all the downsides of introducing a new keyword. (Hence the not-entirely-uncommon suggestion of using "with" for a purpose along these lines, which runs into a different set of problems related to trying to use "with" for two distinct and entirely unrelated purposes).Nick.
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?
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
If it just needs a stream of +1s, I personally like the "given" approach much more than the ":=" approach, for all of the many reasons repeated many times in the various email chains. (I preferred it as "as", but that's been struck down already) (and if it's between ":=" and not having them at all, I would rather just not have them)
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
I'm sorry, but unless there's a sudden landslide of support for 'given' in favor of ':=', I'm really not going to consider it.I'd pronounce "if (x := y) > 0" as either "if y (assigned to x) is greater than zero" or "if x (assigned from y) is greater than zero".
Please no, it's not that easy. I can easily generate a stream of +1s or -1s for any proposal. I'd need well-reasoned explanations and it would have to come from people who are willing to spend significant time writing it up eloquently. Nick has tried his best and failed to convince me. So the bar is high.(Also note that most of the examples that have been brought up lately were meant to illustrate the behavior in esoteric corner cases while I was working out the fine details of the semantics. Users should use this feature sparingly and stay very far away of those corner cases -- but they have to be specified in order to be able to implement this thing.)
You are assuming "given" to improve readability, where I stated ":= is
perfectly clear ", at least in my opinion. Therefore, since clarity is
already achieved, the rest is clutter that reduces readability.
I gather we don't talk about interactive usage.
So, I grepped through part of our code-base. Like it or not, it's almost
always called "match" there.
Like Gustavo, I also have the feeling that long-living, real-world code
tends to have more descriptive names than all those toy examples/arguments.
Cheers,
Sven
I respectfully disagree with your opinion (i.e. you're wrong :-)
Consider:
while (cmd := get_command()).token != CMD_QUIT:
cmd.do_something()
vs:
while cmd.token != CMD_QUIT given cmd = get_command():
cmd.do_something()
I find I write code like this[*] a fair bit, since my major use for
Python is to write remote monitors for embedded kit, so it's pretty much
a real world example. I don't find the first version using ":=" to be
perfectly clear, in fact I think it's rather ugly. That may be partly
the same reaction that many of us had to the asymmetry of assignment
expressions in (over-)complicated comprehensions. The second version
using "given" reads much more naturally to the mathematician in me, and
not too badly to my English half either.
[*] By "like this" I mean the clunky "while true:" spelling, obviously.
--
Rhodri James *-* Kynesim Ltd
Gustavo Carneiro wrote:
IMHO, all these toy examples don't translate well to the real world because they tend to use very short variable names while in real world [good written code] tends to select longer more descriptive variable names.
I don't believe that's always true. It depends on the context.
Sometimes, using long variable names can make code *harder*
to read.
I don't think there's anything unrealistic about this
example:
if m given m = pattern.match(the_string):
nugget = m.group(2)
Most people's short-term memory is good enough to remember
that "m" refers to the match object while they read the
next couple of lines. IMO, using a longer name would serve
no purpose and would just clutter things up.
I've been thinking about this problem, and I think for the If/elif/while cases it's actually possible to allow the "binding is the same as the condition" case to be simplified to:
if command = pattern.match(the_string):
...
elif command = other_pattern.match(the_string):
...
while data = read_data():
...
Allowing this would be part of the definition of the if/elif/while statement headers, rather than a general purpose assignment expression.
A similar enhancement could be made to conditional expressions (adjusting their grammar to permit "EXPR if NAME = EXPR else EXPR") and filter clauses in comprehensions (allowing "EXPR for TARGET in EXPR if NAME = EXPR").
In essence, "if", "elif", and "while" would all allow for an "implied given" clause in order to simplify the 90% case where the desired condition and the bound expression are the same.
Yes, I've considered it. And I don't like the fact that the evaluation
is right-to-left. It isn't a problem when your condition is extremely
simple, but I can guarantee you that people will use this with more
complicated conditions. And when that happens, you have to be aware
that the tail of the statement is actually evaluated before the
primary expression. It's like with Perl:
die("blah blah") unless some_condition
Reverse-order evaluation is confusing and frequently annoying. It's
not an instant failure of the proposal, but it's a serious cost, and
I'd much rather avoid it by using := (which leaves the expression
where it is).
ChrisA
2018-04-06 8:19 GMT+02:00 Serhiy Storchaka <stor...@gmail.com>:
> Using currently supported syntax:
>
> smooth_signal = [average for average in [0] for x in signal for average in [(1-decay)*average + decay*x]]
Go ahead and understand that line in 1 go. It's currently legal syntax
for a running average for a smoothing signal, which remembers
something about it. (Subject: Proposal: A Reduce-Map Comprehension and
a "last" builtin)
You're not allowed to work it out bit by bit, just understand the
entire line or nothing. Any failure of yours proves my point.
> [João]
> How do you read something like " while (cmd := get_command()).token != CMD_QUIT:" in plain english?
while open-paren cee em dee colon is call get-underscore-command
close-paren dot token doesn't equal all-caps cee em dee underscore
quit colon.
Might be some dutch in there.
But far more importantly, I can hold the concept into my head, or just
the parts of it that I need. How we call it in english is actually not
a good argument - whether we can easily mentally parse it is, since I
tend not to code by voice command, but with a keyboard. Your mileage
may vary, but I think we should optimize for keyboard coding over
voice chat coding. And when I need to refer to it, I say "this bit
here" or I copy paste it.
I would write this using a for loop and the two-argument form of iter:
for cmd in iter(get_command, ''):
if cmd.token == CMD_QUIT:
break
cmd.do_something()
or
from itertools import take while
for cmd in takewhile(lambda x: x.token != CMD_QUIT, iter(get_command, '')):
cmd.do_something()
Depending on what get_command actually returns, you might be able to construct a valid sentinel that
doesn't require an explicit test of cmd.token.
(This reminds that I wish ``iter`` could take a predicate instead of a sentinel as its second argument. Then
you could just write
for cmd in iter(get_command, lambda x: x.token == CMD_QUIT):
cmd.do_something()
)
--
Clint
(This reminds that I wish ``iter`` could take a predicate instead of a sentinel as its second argument. Then
you could just write
for cmd in iter(get_command, lambda x: x.token == CMD_QUIT):
cmd.do_something()
)
While cee-em-dee (from get-command) dot token isn't CMD_Quit
ChrisA
Guido van Rossum wrote:
I'd need well-reasoned explanations
My reasoning is essentially the same as what I've already
said about "where". To summarise, "given" sounds like
something an English-speaking mathematician would write,
whereas ":=" doesn't even have an obvious pronunciation.
Some variation on "given" just seems greatly more pythonic
to me.
--
Greg
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
Most people's short-term memory is good enough to remember
that "m" refers to the match object while they read the
next couple of lines. IMO, using a longer name would serve
no purpose and would just clutter things up.
Send Python-ideas mailing list submissions to
python...@python.org
To subscribe or unsubscribe via the World Wide Web, visit
https://mail.python.org/mailman/listinfo/python-ideas
or, via email, send a message with subject or body 'help' to
python-ide...@python.org
You can reach the person managing the list at
python-id...@python.org
When replying, please edit your Subject line so it is more specific
than "Re: Contents of Python-ideas digest..."
Today's Topics:
1. Re: Inline assignments using "given" clauses (Steven D'Aprano)
2. Re: Inline assignments using "given" clauses (Guido van Rossum)
3. Re: Inline assignments using "given" clauses (Guido van Rossum)
4. Re: Inline assignments using "given" clauses (Steven D'Aprano)
5. Re: Inline assignments using "given" clauses (Tim Peters)
----------------------------------------------------------------------
Message: 1
Date: Sat, 12 May 2018 02:17:24 +1000
From: Steven D'Aprano <st...@pearwood.info>
To: python...@python.org
Subject: Re: [Python-ideas] Inline assignments using "given" clauses
Message-ID: <2018051116...@ando.pearwood.info>
Content-Type: text/plain; charset=us-ascii
On Fri, May 11, 2018 at 12:37:43PM +0100, Rhodri James wrote:
> Consider:
>
> while (cmd := get_command()).token != CMD_QUIT:
> cmd.do_something()
>
> vs:
>
> while cmd.token != CMD_QUIT given cmd = get_command():
> cmd.do_something()
Okay, considered. I think the first is preferable.
Much earlier in the PEP 572 discussion, I strongly argued in favour
of the
expr as name
syntax on the basis that the most important part of the overall
expression is "expr", not the assignment target, and therefore that
should come first. Even though I have accepted that "as" is not viable,
I still believe that it is preferable to have the expression first, or
if not first, at least as close to the left as we can get it.
This "given" syntax puts the expr part all the way to the far right of
the line. A line which is made all the longer for needing to use "given"
and redundantly state the target name.
It's like we're trying to maximize the distance the eye has to travel
back and forth when reading.
I have to read to the end of the line before I have any idea where cmd
has come from or what it is. The fact that it comes from a "given"
expression comes as a surprise at the end of the line.
Now obviously this doesn't matter if I'm reading lines of code in
careful detail, but I don't do that all the time. I skim code far more
than I read it in careful detail, and the closer things are to the left,
the more likely I am to see them while skimming. The further out they
are, the easier they are to miss.
I think that "given" will *literally* make reading harder, in that the
eye has to travel further to spot the relevant expression while skimming
over code. As I said, I don't think it makes any difference when reading
closely in detail. But most of my reading of code is skimming to find
the relevant line or section, and then read closely. I would probably
skim a hundred lines for every one I read closely.
We read more code than we write, but writing is important too. I think
the verbosity of "given" (six chars versus two) and the redundancy of
needing to repeat the name of the target even if you only use it once
will soon make using this syntax seem like a chore.
--
Steve
------------------------------
Message: 2
Date: Fri, 11 May 2018 12:25:46 -0400
From: Guido van Rossum <gu...@python.org>
To: Greg Ewing <greg....@canterbury.ac.nz>
Cc: python-ideas <python...@python.org>
Subject: Re: [Python-ideas] Inline assignments using "given" clauses
Message-ID:
<CAP7+vJLR9N4N1g4U3T-DgYGMHAM_a=inDi7dFiF7...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"
Maybe you could propose some kind of syntax using "whereas"? (It can be
used as a preamble.)
On Fri, May 11, 2018 at 3:05 AM, Greg Ewing <greg....@canterbury.ac.nz>
wrote:
> Guido van Rossum wrote:
>
>> I'd need well-reasoned explanations
>>
>
> My reasoning is essentially the same as what I've already
> said about "where". To summarise, "given" sounds like
> something an English-speaking mathematician would write,
> whereas ":=" doesn't even have an obvious pronunciation.
> Some variation on "given" just seems greatly more pythonic
> to me.
>
> --
> Greg
>
> _______________________________________________
> Python-ideas mailing list
> Python...@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180511/d6443de1/attachment-0001.html>
------------------------------
Message: 3
Date: Fri, 11 May 2018 12:33:10 -0400
From: Guido van Rossum <gu...@python.org>
To: Greg Ewing <greg....@canterbury.ac.nz>
Cc: Python-Ideas <python...@python.org>
Subject: Re: [Python-ideas] Inline assignments using "given" clauses
Message-ID:
<CAP7+vJJ-yEyOnO8N4kmyyxs3qAjFyPFv=7SU3GT3T...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"
On Fri, May 11, 2018 at 3:33 AM, Greg Ewing <greg....@canterbury.ac.nz>
wrote:
> Most people's short-term memory is good enough to remember
> that "m" refers to the match object while they read the
> next couple of lines. IMO, using a longer name would serve
> no purpose and would just clutter things up.
Indeed.
A thought just occurred to me. Maybe we need to instigate a cultural shift
where people think about style guides as less dictated by hard-coded rules
that were "passed down from the mountain" and more as derived from research
that we can all understand about usability. A lot more is known about how
human perception and various types of memory and learning work than it was
when the "7 things plus/minus 2" rule was invented (
https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two).
It would be fascinating to imagine a future where language designers could
talk about such topic with as much confidence as they talk about the
efficiency of hash tables.
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180511/808769ad/attachment-0001.html>
------------------------------
Message: 4
Date: Sat, 12 May 2018 02:43:14 +1000
From: Steven D'Aprano <st...@pearwood.info>
To: python...@python.org
Subject: Re: [Python-ideas] Inline assignments using "given" clauses
Message-ID: <2018051116...@ando.pearwood.info>
Content-Type: text/plain; charset=iso-8859-1
On Fri, May 11, 2018 at 03:47:05PM +0200, Jo?o Santos wrote:
> How do you read something like " while (cmd := get_command()).token !=
> CMD_QUIT:" in plain english?
I wouldn't if I could avoid it. I hardly ever program by talking about
code in plain English. Often the lines are gobblydegook:
zreplace = '%c%02d%02d' % (sign, h, m) # datetime.py
and even when they are technically pronouncable English:
# subprocess.py
(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) =
self._get_handles(stdin, stdout, stderr)
my brain would glaze over by the second "p2c". I prefer to read and
write code than speak it, and if I need to discuss it, I prefer to use a
whiteboard so I can write things down.
But if I really needed to, I'd probably start by reading it as:
while open bracket command defined as get-command close bracket dot
token is not equal to command-quit
and then I'd probably drop the "defined" and swap the order around.
Actually, that's not true. I probably wouldn't say that, not in a
real conversation. What I'd probably say is,
So, like, I've got this command object, see, which I get
from calling get-command, right, and so I get the, um,
token attribute, okay, and if that's not equal to the
quit value, I loop until it is. Right?
(And this is why I prefer *writing* code than *saying* code.)
--
Steve
------------------------------
Message: 5
Date: Fri, 11 May 2018 11:45:13 -0500
From: Tim Peters <tim.p...@gmail.com>
To: Nick Coghlan <ncog...@gmail.com>
Cc: Greg Ewing <greg....@canterbury.ac.nz>, Python-Ideas
<python...@python.org>
Subject: Re: [Python-ideas] Inline assignments using "given" clauses
Message-ID:
<CAExdVNnm0AG4KyjWg-w8CHkoVMh4iPbJtFzO4eApTKLK23=q...@mail.gmail.com>
Content-Type: text/plain; charset="UTF-8"
------------------------------
Subject: Digest Footer
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
------------------------------
End of Python-ideas Digest, Vol 138, Issue 90
*********************************************
> while (cmd := get_command()).token != CMD_QUIT:
> cmd.do_something()
On 11/05/2018 15:04, Jacco van Dorp wrote:
> A while ago, we had this gem:
>
> 2018-04-06 8:19 GMT+02:00 Serhiy Storchaka <stor...@gmail.com>:
>> Using currently supported syntax:
>>
>> smooth_signal = [average for average in [0] for x in signal for average in [(1-decay)*average + decay*x]]
> Go ahead and understand that line in 1 go. It's currently legal syntax
> for a running average for a smoothing signal, which remembers
> something about it. (Subject: Proposal: A Reduce-Map Comprehension and
> a "last" builtin)
>
> You're not allowed to work it out bit by bit, just understand the
> entire line or nothing. Any failure of yours proves my point.
>
>> [João]
>> How do you read something like " while (cmd := get_command()).token != CMD_QUIT:" in plain english?
> while open-paren cee em dee colon is call get-underscore-command
> close-paren dot token doesn't equal all-caps cee em dee underscore
> quit colon.
>
> Might be some dutch in there.
>
> But far more importantly, I can hold the concept into my head, or just
> the parts of it that I need. How we call it in english is actually not
> a good argument - whether we can easily mentally parse it is, since I
> tend not to code by voice command, but with a keyboard. Your mileage
> may vary, but I think we should optimize for keyboard coding over
> voice chat coding. And when I need to refer to it, I say "this bit
> here" or I copy paste it.
> _______________________________________________
> Python-ideas mailing list
> Python...@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
> ---
> This email has been checked for viruses by AVG.
> http://www.avg.com
[Matt Arcidy]
>> Note Tim came up with a real metric:
>> 2 * count(":=")/len(statement).
>> It's objective. it's just unclear if a higher score is better or worse.
>> However, one could say "a Tim of .3 is considered too high" as a guideline.
[Steven D'Aprano]
> I think Tim was making a joke about demanding objective measurements of
> subjective things.
>
> Certainly he hasn't done any research or study to justify that metric.
> He just plucked the formula out of thin air.
It was the outcome of an intense 17-year research project.
> Or at least no peer reviewed research.
Au contraire! My peers are here, and that message was reviewed by at
least 3 people on this list.
That said, I am a fan of objectively measuring subjective things, just
not of taking the measurements seriously ;-)
If people do want to take it seriously, check out prior Python art first:
Concerning my previous email,
Yes, my mistake. I'd forgotten (ironically) that the whole point is that it's an expression itself.
So
> while (value:=get_next_pool_item()).in_use:
> print(value.refcount())
would be the appropriate analogue.
Consequently, my example is invalid. A better example would have been where one needs to access more than one attribute of the expressionwhile (node.x, node.y) > (5.0, 5.0) given node = get_neighbours(node):
pass
There was some criticism about the length of the `given`, maybe it is possible to _repurpose_ `with` keyword:while (x, y) > (5.0, 5.0) given x, y = get_neighbours(node):pass
while (x, y) > (5.0, 5.0) with x, y = get_neighbours(node):pass
I'm sorry, but unless there's a sudden landslide of support for 'given' in favor of ':=', I'm really not going to consider it.I'd pronounce "if (x := y) > 0" as either "if y (assigned to x) is greater than zero" or "if x (assigned from y) is greater than zero".On Thu, May 10, 2018 at 6:39 AM, Nick Coghlan <ncog...@gmail.com> wrote:On 8 May 2018 at 04:19, Brett Cannon <br...@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)):
passRather than the more explicit:
while not probable_prime(candidate) given (candidate =
highbit | randrange(1, highbit, 2)):
passHowever, I'd still consider both of those easier to follow than:
while not probable_prime(candidate := highbit | randrange(1, highbit, 2)):
passsince 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 expressionThat 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 | ncog...@gmail.com | Brisbane, Australia
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/