Path: csiph.com!newsfeed.hal-mli.net!feeder3.hal-mli.net!newsfeed.hal-mli.net!feeder1.hal-mli.net!newsfeed.xs4all.nl!newsfeed1.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.021 X-Spam-Evidence: '*H*': 0.96; '*S*': 0.00; 'alain': 0.09; 'repeated': 0.09; 'subject:while': 0.09; 'python': 0.11; 'def': 0.12; 'language.': 0.14; 'callee': 0.16; 'choice,': 0.16; 'feasible': 0.16; 'fine.': 0.16; 'from:addr:mrabarnett.plus.com': 0.16; 'from:addr:python': 0.16; 'from:name:mrab': 0.16; 'message- id:@mrabarnett.plus.com': 0.16; 'optimised': 0.16; 'received:84.93': 0.16; 'received:84.93.230': 0.16; 'subject:recursion': 0.16; 'essential': 0.16; 'followed': 0.16; 'wrote:': 0.18; 'replacing': 0.19; 'stack': 0.19; '>>>': 0.22; 'programming': 0.22; 'header:User-Agent:1': 0.23; '(or': 0.24; 'code:': 0.26; 'header:In-Reply-To:1': 0.27; 'idea': 0.28; 'point': 0.28; 'function': 0.29; "doesn't": 0.30; '(like': 0.30; "i'm": 0.30; 'could': 0.34; "can't": 0.35; 'received:84': 0.35; 'keyword': 0.36; 'scheme': 0.36; 'done': 0.36; 'should': 0.36; 'behind': 0.37; 'clear': 0.37; 'implement': 0.38; 'to:addr:python- list': 0.38; 'fact': 0.38; 'to:addr:python.org': 0.39; 'everybody': 0.60; 'full': 0.61; 'show': 0.63; 'name': 0.63; 'refer': 0.63; 'more': 0.64; 'here': 0.66; 'header:Reply-To:1': 0.67; 'reply-to:no real name:2**0': 0.71; '*and*': 0.84; 'pardon': 0.84; 'reply-to:addr:python.org': 0.84; 'dynamics': 0.91; 'notion': 0.91; 'procedural': 0.91; 'was:': 0.91 X-CM-Score: 0.00 X-CNFS-Analysis: v=2.1 cv=PIY2p5aC c=1 sm=1 tr=0 a=0nF1XD0wxitMEM03M9B4ZQ==:117 a=0nF1XD0wxitMEM03M9B4ZQ==:17 a=0Bzu9jTXAAAA:8 a=LqG8EI-UCiYA:10 a=DVkrMzQw-UUA:10 a=ihvODaAuJD4A:10 a=OUOv7kDek9cA:10 a=8nJEP1OIZ-IA:10 a=EBOSESyhAAAA:8 a=8AHkEIZyAAAA:8 a=ZPwmbRZxN1IA:10 a=fgQzWdu-UIQOK45EN8sA:9 a=wPNLvfGTeEIA:10 X-AUTH: mrabarnett:2500 Date: Mon, 07 Oct 2013 22:39:40 +0100 From: MRAB User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:24.0) Gecko/20100101 Thunderbird/24.0 MIME-Version: 1.0 To: python-list@python.org Subject: Re: Tail recursion to while iteration in 2 easy steps References: <87had0axxy.fsf@dpt-info.u-strasbg.fr> <524C80B6.3010204@unistra.fr> <87li292wnt.fsf@dpt-info.u-strasbg.fr> <878uy52ea0.fsf@dpt-info.u-strasbg.fr> <5252F610.9040403@rece.vub.ac.be> In-Reply-To: <5252F610.9040403@rece.vub.ac.be> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: python-list@python.org List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 62 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1381181988 news.xs4all.nl 15942 [2001:888:2000:d::a6]:40524 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:56333 On 07/10/2013 18:57, Antoon Pardon wrote: > Op 07-10-13 19:15, Alain Ketterlin schreef: >>> I want to consider here what it would mean to concretely >>> implement the abstract notion 'disallow rebinding of function >>> names' and show what would be behind calling the idea 'not >>> feasible'. >> >> Again, I'm more concerned about the function than about the name. >> >> And the fact that "disallow rebinding of function names" is not >> feasible in Python is a design choice, not an essential >> characteristic of every programming language. >> >> That's fine. My point was: you can't at the same time have full >> dynamicity *and* procedural optimizations (like tail call opt). >> Everybody should be clear about the trade-off. > > Your wrong. Full dynamics is not in contradiction with tail call > optimisation. Scheme has already done it for years. You can rebind > names to other functions in scheme and scheme still has working tail > call optimisatiosn. > Consider this code: def fact(n, acc=1): if n <= 1: return acc return fact(n-1, n*acc) It compiles to this: >>> dis.dis(fact) 2 0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (1) 6 COMPARE_OP 1 (<=) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_FAST 1 (acc) 15 RETURN_VALUE 4 >> 16 LOAD_GLOBAL 0 (fact) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 1 (1) 25 BINARY_SUBTRACT 26 LOAD_FAST 0 (n) 29 LOAD_FAST 1 (acc) 32 BINARY_MULTIPLY 33 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 36 RETURN_VALUE I think that CALL_FUNCTION immediately followed by RETURN_VALUE could be tail-call optimised by dropping the caller's stack frame provided that (like in this case) the callee doesn't refer to any name in the callers stack frame (nonlocal). You could also consider replacing the caller's stack frame with a smaller pseudo-frame, perhaps compressing multiple pseudo-frames or repeated sequences of pseudo-frames into a single pseudo-frame, so that it could still generate the same traceback as before (or an compressed traceback like what was discussed on python-ideas in the threads "Compressing excepthook output" and "Idea: Compressing the stack on the fly").