if <expression> as <variable>
Hi! I’ve been having this idea for a few years and I thought I finally see if what others think of it. I have no experience in language design and I don’t know if this is something I’ve picked up in some other language. I also do not know what the ramifications of implementing this idea would be. I just keep thinking about it :) I quite often write code like the following in python: result = computation() if result: do_something_with_computation(result) More often than not this snippet evolves from something like this: if computation(): … That is, I use the truthiness of the value at first. As the code grows I refactor to actually do something with the result. What I would love to see is the following syntax instead, which to me is much cleaner: if computation() as result: do_something_with_result(result) Basically the result variable would be the result of the if condition’s expression and it would be available the same way it would be if we used my initial snippet (much the same way that the result of with expressions also stays around outside the with-block). Any feedback is appreciated :) Cheers, Denis
On 7 September 2017 at 11:43, Denis Krienbühl <denis@href.ch> wrote:
What I would love to see is the following syntax instead, which to me is much cleaner:
if computation() as result: do_something_with_result(result)
Hi - thanks for your suggestion! This has actually come up quite a lot in the past. Here's a couple of links to threads you might want to read (it's not surprising if you missed these, it's not that easy to come up with a good search term for this topic). https://mail.python.org/pipermail/python-ideas/2012-January/013461.html https://mail.python.org/pipermail/python-ideas/2009-March/003423.html (This thread includes a note by Guido that he intentionally left out this functionality) In summary, it's a reasonably commonly suggested idea, but there's not enough benefit to warrant adding it to the language. Paul
On 7 Sep 2017, at 13:11, Paul Moore <p.f.moore@gmail.com> wrote:
On 7 September 2017 at 11:43, Denis Krienbühl <denis@href.ch> wrote:
What I would love to see is the following syntax instead, which to me is much cleaner:
if computation() as result: do_something_with_result(result)
Hi - thanks for your suggestion! This has actually come up quite a lot in the past. Here's a couple of links to threads you might want to read (it's not surprising if you missed these, it's not that easy to come up with a good search term for this topic).
https://mail.python.org/pipermail/python-ideas/2012-January/013461.html https://mail.python.org/pipermail/python-ideas/2009-March/003423.html (This thread includes a note by Guido that he intentionally left out this functionality)
In summary, it's a reasonably commonly suggested idea, but there's not enough benefit to warrant adding it to the language.
Paul
I see, thank you for digging those threads up. I’ll read them to learn a thing or two :)
Sent: Thursday, September 07, 2017 at 6:43 AM From: "Denis Krienbühl" <denis@href.ch> To: python-ideas@python.org Subject: [Python-ideas] if <expression> as <variable>
Hi!
I’ve been having this idea for a few years and I thought I finally see if what others think of it. I have no experience in language design and I don’t know if this is something I’ve picked up in some other language. I also do not know what the ramifications of implementing this idea would be. I just keep thinking about it :)
I quite often write code like the following in python:
result = computation() if result: do_something_with_computation(result)
More often than not this snippet evolves from something like this:
if computation(): …
That is, I use the truthiness of the value at first. As the code grows I refactor to actually do something with the result.
What I would love to see is the following syntax instead, which to me is much cleaner:
if computation() as result: do_something_with_result(result)
Basically the result variable would be the result of the if condition’s expression and it would be available the same way it would be if we used my initial snippet (much the same way that the result of with expressions also stays around outside the with-block).
Any feedback is appreciated :)
I also often wonder why we are left doing an assignment and test. You have two options: 1. assign to a variable then test and use 2. repeat the function call I would offer that 'with' [sh|c]ould be used: with test() as x: handle_truthy(x) else: handle_falsey() # do we provide x here too? Because None vs False?
On Thu, Sep 07, 2017 at 04:36:40PM +0200, Jason H wrote:
I also often wonder why we are left doing an assignment and test. You have two options: 1. assign to a variable then test and use 2. repeat the function call
Personally, I don't see what's wrong with the "assign then test" idiom. x = something() if x: do_stuff()
I would offer that 'with' [sh|c]ould be used: with test() as x: handle_truthy(x) else: handle_falsey() # do we provide x here too? Because None vs False?
This would cause confusing errors and mysterious behaviour, depending on whether the test() object was a context manager or not. Which should take priority? If you see: with spam() as x: do_stuff is that a context manager with block (like "with open(...) as f") or your boolean if test in disguise? Having "with" sometimes be a disguised "if" and sometimes a regular "with" will make it really, really hard to reason about code. -- Steve
Sadly it’s hard to create a context manager that skips its body like this: with unpack(computation()) as result: do_something_with_result(result) You can do it with some hackery like described here: https://stackoverflow.com/a/12594789/247482 class unpack: def __init__(self, pred): self.pred = pred def __enter__(self): if self.pred: return self.pred # else skip the with block’s body sys.settrace(lambda *args, **kw: None) frame = inspect.currentframe(1) frame.f_trace = self.trace def trace(self, frame, event, arg): raise def __exit__(self, type, value, traceback): return True # suppress the exception Steven D'Aprano <steve@pearwood.info> schrieb am Do., 7. Sep. 2017 um 18:26 Uhr:
On Thu, Sep 07, 2017 at 04:36:40PM +0200, Jason H wrote:
I also often wonder why we are left doing an assignment and test. You have two options: 1. assign to a variable then test and use 2. repeat the function call
Personally, I don't see what's wrong with the "assign then test" idiom.
x = something() if x: do_stuff()
I would offer that 'with' [sh|c]ould be used: with test() as x: handle_truthy(x) else: handle_falsey() # do we provide x here too? Because None vs False?
This would cause confusing errors and mysterious behaviour, depending on whether the test() object was a context manager or not. Which should take priority? If you see:
with spam() as x: do_stuff
is that a context manager with block (like "with open(...) as f") or your boolean if test in disguise?
Having "with" sometimes be a disguised "if" and sometimes a regular "with" will make it really, really hard to reason about code.
-- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
sorry, it’s a bit more difficult. this works: https://gist.github.com/flying-sheep/86dfcc1bdd71a33fa3483b83e254084c Philipp A. <flying-sheep@web.de> schrieb am Do., 7. Sep. 2017 um 21:18 Uhr:
Sadly it’s hard to create a context manager that skips its body like this:
with unpack(computation()) as result: do_something_with_result(result)
You can do it with some hackery like described here: https://stackoverflow.com/a/12594789/247482
class unpack: def __init__(self, pred): self.pred = pred
def __enter__(self): if self.pred: return self.pred # else skip the with block’s body sys.settrace(lambda *args, **kw: None) frame = inspect.currentframe(1) frame.f_trace = self.trace
def trace(self, frame, event, arg): raise
def __exit__(self, type, value, traceback): return True # suppress the exception
Steven D'Aprano <steve@pearwood.info> schrieb am Do., 7. Sep. 2017 um 18:26 Uhr:
On Thu, Sep 07, 2017 at 04:36:40PM +0200, Jason H wrote:
I also often wonder why we are left doing an assignment and test. You have two options: 1. assign to a variable then test and use 2. repeat the function call
Personally, I don't see what's wrong with the "assign then test" idiom.
x = something() if x: do_stuff()
I would offer that 'with' [sh|c]ould be used: with test() as x: handle_truthy(x) else: handle_falsey() # do we provide x here too? Because None vs False?
This would cause confusing errors and mysterious behaviour, depending on whether the test() object was a context manager or not. Which should take priority? If you see:
with spam() as x: do_stuff
is that a context manager with block (like "with open(...) as f") or your boolean if test in disguise?
Having "with" sometimes be a disguised "if" and sometimes a regular "with" will make it really, really hard to reason about code.
-- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On Fri, Sep 8, 2017 at 5:40 AM, Philipp A. <flying-sheep@web.de> wrote:
sorry, it’s a bit more difficult. this works: https://gist.github.com/flying-sheep/86dfcc1bdd71a33fa3483b83e254084c
If this can be made to work - even hackily - can it be added into contextlib.contextmanager (or technically its helper class)? Currently, its __enter__ looks like this: def __enter__(self): try: return next(self.gen) except StopIteration: raise RuntimeError("generator didn't yield") from None If that raise were replaced with the hackiness of skipping the body, we could wrap everything up nicely: @contextlib.contextmanager def iff(thing): if thing: yield thing # otherwise don't yield for i in range(1, 11): with iff(random.randrange(3)) as val: print(i, val) # won't print any zeroes ChrisA
participants (6)
-
Chris Angelico
-
Denis Krienbühl
-
Jason H
-
Paul Moore
-
Philipp A.
-
Steven D'Aprano