Path: csiph.com!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail From: Chris Angelico Newsgroups: comp.lang.python Subject: Re: for / while else doesn't make sense Date: Sat, 21 May 2016 17:29:20 +1000 Lines: 71 Message-ID: References: <573dfc0f$0$1586$c3e8da3$5496439d@news.astraweb.com> <573e54f7$0$1615$c3e8da3$5496439d@news.astraweb.com> <57400C22.7050706@lucidity.plus.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Trace: news.uni-berlin.de Mk3z8puVc0w/xhH/mWTihAkDIsXpzJ0sfsgBoqXU1mDA== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'python,': 0.02; 'else:': 0.03; 'value,': 0.03; '(even': 0.05; 'cpython': 0.05; 'discard': 0.05; 'model,': 0.05; '21,': 0.07; 'clause': 0.07; 'cc:addr :python-list': 0.09; '__future__': 0.09; 'none.': 0.09; 'subject:while': 0.09; 'example:': 0.10; 'python': 0.10; 'syntax': 0.13; 'def': 0.13; '"break"': 0.16; '"for"': 0.16; '(f)': 0.16; '2016': 0.16; 'bug,': 0.16; 'complains': 0.16; 'erik': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'happily': 0.16; 'hint': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'sources.': 0.16; 'subject:make': 0.16; 'wrote:': 0.16; 'say,': 0.18; '(in': 0.18; 'runs': 0.18; 'language': 0.19; '>>>': 0.20; 'load': 0.20; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'work,': 0.21; 'pass': 0.22; 'code,': 0.23; 'code.': 0.23; 'decide': 0.23; 'sat,': 0.23; 'import': 0.24; '(this': 0.24; 'header:In-Reply-To:1': 0.24; 'testing': 0.25; "doesn't": 0.26; 'example': 0.26; 'error': 0.27; 'switch': 0.27; 'message-id:@mail.gmail.com': 0.27; 'function': 0.28; 'this.': 0.28; 'fine': 0.28; 'behaviour': 0.29; 'command-line': 0.29; '(including': 0.30; 'code': 0.30; 'certainly': 0.30; 'probably': 0.31; "can't": 0.32; "d'aprano": 0.33; 'instances': 0.33; 'jump': 0.33; 'steven': 0.33; 'similar': 0.33; 'add': 0.34; 'received:google.com': 0.35; 'so,': 0.35; 'could': 0.35; 'done': 0.35; 'returning': 0.35; 'received:74.125.82': 0.35; "isn't": 0.35; 'problem.': 0.35; 'but': 0.36; 'should': 0.36; 'there': 0.36; 'keyword': 0.36; 'pm,': 0.36; 'subject:: ': 0.37; 'turn': 0.37; '(2)': 0.37; 'things': 0.38; 'doing': 0.38; 'experience,': 0.38; '(1)': 0.38; 'wrong': 0.38; 'mean': 0.38; 'why': 0.39; 'test': 0.39; 'does': 0.39; "didn't": 0.39; 'some': 0.40; 'your': 0.60; 'skip:u 10': 0.61; 'default': 0.61; 'side': 0.62; 'back': 0.62; 'skip:n 10': 0.62; 'subject: / ': 0.63; 'fundamental': 0.66; 'evaluate': 0.72; 'chrisa': 0.84; 'construct': 0.84; 'longest': 0.84; 'subject:else': 0.84; 'subject:sense': 0.84; 'to:none': 0.91; 'effects,': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc; bh=QT+WAQer6v4dVZsNjyTjoqOvnwInY8xL6H8zNpGqEc0=; b=0nb28YtKm0RZ6DQbwRrXIMzGt6ZDOFOgk6NQu7MVfYEvGEXKUmKWz8Cg0kPSv5ZYT+ ayGbDn+9afaqe8ESTzv1tfHnyJKNJ5QkKfghbXvItiGA869ddMBU+Y+hhvkYoWpgP2xL 6gacP6IbdJYw/GcYHhcHNJ7sCRw5mwJ7td/0rSQCgW5EImwM5NRz/52hG53f/UirC2se jVXXCAhiKJqghEsgu84ps/2lCyGjEFW/DF64AQJ9rAshlm0fLDVx+ykAJxbtFj/9Hjzu JCtYrhotKOehhmB+UCnvVgV+RnWP+wPb99cVO4R4bSJO5yeIYucPHvhbGlL0mHfxpIAN eV8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:cc; bh=QT+WAQer6v4dVZsNjyTjoqOvnwInY8xL6H8zNpGqEc0=; b=dnamHt8U7V0+JpFxApkWb5An341lVRFJ39UpOo5YI8SPAA9/0oUeZzvd/4CVaqAQL0 UN+l8k2X4h/w5s0oa1BwmVGMavGwKW21E1oyHVBdiAPPoHMuEL3CX7wPIDOXSlukudju 2ZY3Pn20shVwDDVTnUXiKXdUf1VMAUYzbpkJdJN0t4XPVuiY/RyRCRURlZaeTJLCg8ca zfm5vJ/0nLBS8xPdYutkELpdQ72AEnqXJNwwO/mkVMydmRra3wsdf4RQquJrXx8vTAUO 0aa3Fdm7T82waVPQiJvUm/TEVJ46P3LnX4ahwmUbhOWuqPL/69Viz8BTPLA/fC5h5RQg lJyQ== X-Gm-Message-State: AOPr4FVOU1nYYAgBRDoEyk5gz4/OWD4oSBW9Qx4TtOewC7ZfI5zt0B8CmQ70v4YXmvqsQPaNHgTUSaN564oeug== X-Received: by 10.194.110.234 with SMTP id id10mr6857229wjb.30.1463815760335; Sat, 21 May 2016 00:29:20 -0700 (PDT) In-Reply-To: <57400C22.7050706@lucidity.plus.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Mailman-Original-Message-ID: X-Mailman-Original-References: <573dfc0f$0$1586$c3e8da3$5496439d@news.astraweb.com> <573e54f7$0$1615$c3e8da3$5496439d@news.astraweb.com> <57400C22.7050706@lucidity.plus.com> Xref: csiph.com comp.lang.python:108901 On Sat, May 21, 2016 at 5:20 PM, Erik wrote: > On 20/05/16 01:06, Steven D'Aprano wrote: > >> In my experience, some people (including me) misunderstand "for...else" to >> mean that the else block runs if the for block *doesn't*. It took me the >> longest time to understand why this didn't work as I expected: >> >> for x in seq: >> pass >> else: >> print("seq is empty") > > > So why don't we consider if that should be a syntax error - "else" clause on > "for" loop with no "break" in its body? I know that doesn't change your > fundamental mental model, but it's a hint that it's wrong :) > > As it's backwards-incompatible, it could be introduced using a __future__ > import (a precedent is 'generators' and the "yield" keyword back in the day) > which those who would like the new check could add to the top of their > sources. > > But also, as you say, any instances of that construct in the wild is almost > certainly a bug, so it would be good to be able to test code using a > command-line or similar switch to turn on the behaviour by default for > testing existing bodies of code. > > I notice that pylint complains about this (as a warning). Is there any > reason why this should _not_ just be considered an error and be done with > it? Because it's not the language parser's job to decide what's "sensible" and what's "not sensible". That's a linter's job. Some things fundamentally can't work, but others work fine and might just be not-very-useful - for example: def f(x): x if x <= 2 else x * f(x-1) This is syntactically-legal Python code, but it probably isn't doing what you want it to (in Python, a bare final expression does NOT become the function's return value, although that does happen in other languages). A linter should look at this and give a warning (even if the else part has side effects, the first part can't, and the condition shouldn't), but the language will happily evaluate it (this example from CPython 3.6): >>> dis.dis(f) 2 0 LOAD_FAST 0 (x) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 1 (<=) 9 POP_JUMP_IF_FALSE 18 12 LOAD_FAST 0 (x) 15 JUMP_FORWARD 17 (to 35) >> 18 LOAD_FAST 0 (x) 21 LOAD_GLOBAL 0 (f) 24 LOAD_FAST 0 (x) 27 LOAD_CONST 2 (1) 30 BINARY_SUBTRACT 31 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 34 BINARY_MULTIPLY >> 35 POP_TOP 36 LOAD_CONST 0 (None) 39 RETURN_VALUE So, yes, this function might load up the value of x (position 12), then jump to 35 and discard that value, before unconditionally returning None. Not a problem. It's up to the linter, and ONLY the linter, to tell you about this. ChrisA