Re: setting variables in outer functions
Hrvoje Niksic a écrit : Chris Mellon [EMAIL PROTECTED] writes: I have no idea why someone who already has a working, object system would want to implement their own on top of closures. This subthread is getting ridiculous -- closures are *not* useful only for implementing object systems! The object system thing is just a method of teaching abstractions popularized by SICP. Abstractions normally taken for granted, such as objects, or even expression evaluation, are implemented from scratch, using only the most basic primitives available. In a Lisp-like language with lexical scope, the most basic storage primitive is the lexical environment itself[1]. In real-life code, closures are used to implement callbacks with automatic access to their lexical environment without the need for the bogus additional void * argument one so often sees in C callbacks, and without communication through global variables. If the callbacks can access variables in the outer scope, it's only logical (and useful) for them to be able to change them. Prohibiting modification reduces the usefulness of closures and causes ugly workarounds such as the avar[0] pattern. If closures were useful only for implementing bogus object systems, neither they nor nonlocal would have made it to Python in the first place. Indeed. But please read carefully the classic piece of wisdom quoted by Diez in his answer. Then remember that in Python, callable objects doesn't need to be functions, and most of what can be done (and is usually done in FPLs) can be done with objects. Look at the sample Python implementation of partial evaluation, or at all the so-called decorators that are not functions but really classes. I do use Python's closures quite a lot myself, because it's often simpler than doing it the OO way. But for whatever slightly more involved, I prefer to write my own classes, and I'll still do so if and when Python grows full-blown closures. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Duncan Booth [EMAIL PROTECTED] writes: In real life code methods are used to implement callbacks When I said closures are used ..., I wasn't trying to be preachy about how I think callbacks should be implemented, just explaining the use (and usefulness) of *closures*. I'm not saying closures are the only method of implementing stateful callbacks, nor that they're the best method around in all circumstances. What is your point here? I was simply responding to a subthread that only evaluated closures as a SICP-style OOP implementation mechanism. That is missing the point of closures. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Hrvoje Niksic [EMAIL PROTECTED] wrote: In real-life code, closures are used to implement callbacks with automatic access to their lexical environment without the need for the bogus additional void * argument one so often sees in C callbacks, and without communication through global variables. If the callbacks can access variables in the outer scope, it's only logical (and useful) for them to be able to change them. Prohibiting modification reduces the usefulness of closures and causes ugly workarounds such as the avar[0] pattern. In real life code methods are used to implement callbacks with automatic access to their environment without the need for any C type hacks. What is your point here? Python isn't C (or Javascript). If you have a function which takes a callback in Python you just pass it a bound method and you have all the context you want without resorting to ugly workrounds. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On Oct 31, 5:59 pm, Chris Mellon [EMAIL PROTECTED] wrote: On Oct 31, 2007 5:49 PM, Dustan [EMAIL PROTECTED] wrote: [snip] I'm not going to respond to any of this, but I'm just going to say: I'm not claiming that the use of closures is common. I'm just claiming that it can be useful. I have used closures exactly once. I feel that that one time, it was for a good cause. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On 2007-11-01, Hrvoje Niksic [EMAIL PROTECTED] wrote: Duncan Booth [EMAIL PROTECTED] writes: In real life code methods are used to implement callbacks When I said closures are used ..., I wasn't trying to be preachy about how I think callbacks should be implemented, just explaining the use (and usefulness) of *closures*. I'm not saying closures are the only method of implementing stateful callbacks, nor that they're the best method around in all circumstances. What is your point here? I was simply responding to a subthread that only evaluated closures as a SICP-style OOP implementation mechanism. That is missing the point of closures. It really depends on how wide your definition of primitive object system is. Can you come up with a use-case for nonlocal that doesn't appear to be a primitive object system? -- Neil Cerutti To succeed in the world it is not enough to be stupid, you must also be well- mannered. --Voltaire -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On Oct 30, 11:29 am, Duncan Booth [EMAIL PROTECTED] wrote: Neil Cerutti [EMAIL PROTECTED] wrote: It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. def account(opening_balance): balance = opening_balance def get_balance(): nonlocal balance return balance def post_transaction(x): nonlocal balance balance += x return balance, post_transaction fred_balance, fred_post = account(1500) joe_balance, joe_post = account(12) fred_post(20) joe_post(-10) fred_balance() TypeError: 'int' object is not callable 1520 joe_balance() TypeError: 'int' object is not callable 2 Python classes will of course nearly always win, though the idiom looks like it might be faster (I don't have Python 3000 to try it out). Python classes might be less error prone. Why would using classes make your code any less prone to typographical errors? -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Dustan [EMAIL PROTECTED] wrote: On Oct 30, 11:29 am, Duncan Booth [EMAIL PROTECTED] wrote: Neil Cerutti [EMAIL PROTECTED] wrote: It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. def account(opening_balance): balance = opening_balance def get_balance(): nonlocal balance return balance def post_transaction(x): nonlocal balance balance += x return balance, post_transaction fred_balance, fred_post = account(1500) joe_balance, joe_post = account(12) fred_post(20) joe_post(-10) fred_balance() TypeError: 'int' object is not callable 1520 joe_balance() TypeError: 'int' object is not callable 2 Python classes will of course nearly always win, though the idiom looks like it might be faster (I don't have Python 3000 to try it out). Python classes might be less error prone. Why would using classes make your code any less prone to typographical errors? Lots of reasons: shorter and clearer code being high on the list. The class equivalent would be: class Account(object): def __init__(self, opening_balance): self.balance = opening_balance def post_transaction(self, x): self.balance += x fred = Account(1500) joe = Account(12) fred.post_transaction(20) joe.post_transaction(-10) fred.balance 1520 joe.balance 2 There is no scope for the particular error I highlighted: you no longer have the duplication of declaring the functions and then returning them. Also you don't need the accessor function at all (and if at some point in the future you do want it you can make it a property). You don't have to invent separate names for each of the returned functions: the dot notation suddenly makes that a no brainer. Also the class is easier to extend: you no longer have to find and change every call to account() if you want to add another method: just add it. BTW, I put both the original code with corrections, and the class version into a file and timed them running with Python 3 alpha 1, the nested scope version is slightly faster: 5.03usec per loop against 5.77usec for the class version, but minor changes to the code can skew the result either way (put in more attribute accesses and the class wins, add in more method calls and the function wins). -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On Oct 31, 7:08 am, Duncan Booth [EMAIL PROTECTED] wrote: Dustan [EMAIL PROTECTED] wrote: On Oct 30, 11:29 am, Duncan Booth [EMAIL PROTECTED] wrote: Neil Cerutti [EMAIL PROTECTED] wrote: It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. def account(opening_balance): balance = opening_balance def get_balance(): nonlocal balance return balance def post_transaction(x): nonlocal balance balance += x return balance, post_transaction fred_balance, fred_post = account(1500) joe_balance, joe_post = account(12) fred_post(20) joe_post(-10) fred_balance() TypeError: 'int' object is not callable 1520 joe_balance() TypeError: 'int' object is not callable 2 Python classes will of course nearly always win, though the idiom looks like it might be faster (I don't have Python 3000 to try it out). Python classes might be less error prone. Why would using classes make your code any less prone to typographical errors? Lots of reasons: shorter and clearer code being high on the list. It wouldn't be necessarily shorter, depending on what you're working with. Clearer is a matter of opinion. The class equivalent would be: class Account(object): def __init__(self, opening_balance): self.balance = opening_balance def post_transaction(self, x): self.balance += x fred = Account(1500) joe = Account(12) fred.post_transaction(20) joe.post_transaction(-10) fred.balance 1520 joe.balance 2 There is no scope for the particular error I highlighted: you no longer have the duplication of declaring the functions and then returning them. The 'particular error' you highlighted was a typographical error, which can happen in any code. Sure, you can't have the exact same typographical error, but that's what happens when you switch between paradigms. Also you don't need the accessor function at all (and if at some point in the future you do want it you can make it a property). You don't have to invent separate names for each of the returned functions: the dot notation suddenly makes that a no brainer. Fair enough; you got two valid arguments there. Also the class is easier to extend: you no longer have to find and change every call to account() if you want to add another method: just add it. Of course, there are cases where you'll never want to extend it. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On Oct 31, 2007 5:49 PM, Dustan [EMAIL PROTECTED] wrote: On Oct 31, 7:08 am, Duncan Booth [EMAIL PROTECTED] wrote: Dustan [EMAIL PROTECTED] wrote: On Oct 30, 11:29 am, Duncan Booth [EMAIL PROTECTED] wrote: Neil Cerutti [EMAIL PROTECTED] wrote: It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. def account(opening_balance): balance = opening_balance def get_balance(): nonlocal balance return balance def post_transaction(x): nonlocal balance balance += x return balance, post_transaction fred_balance, fred_post = account(1500) joe_balance, joe_post = account(12) fred_post(20) joe_post(-10) fred_balance() TypeError: 'int' object is not callable 1520 joe_balance() TypeError: 'int' object is not callable 2 Python classes will of course nearly always win, though the idiom looks like it might be faster (I don't have Python 3000 to try it out). Python classes might be less error prone. Why would using classes make your code any less prone to typographical errors? Lots of reasons: shorter and clearer code being high on the list. It wouldn't be necessarily shorter, depending on what you're working with. Clearer is a matter of opinion. It's going to be shorter in any non-trivial example, and even in most trivial ones (as shown). Clearer may be a matter of opinion, but the less complicated the code you're looking at is, the less chance you have to make an error. The class equivalent would be: class Account(object): def __init__(self, opening_balance): self.balance = opening_balance def post_transaction(self, x): self.balance += x fred = Account(1500) joe = Account(12) fred.post_transaction(20) joe.post_transaction(-10) fred.balance 1520 joe.balance 2 There is no scope for the particular error I highlighted: you no longer have the duplication of declaring the functions and then returning them. The 'particular error' you highlighted was a typographical error, which can happen in any code. Sure, you can't have the exact same typographical error, but that's what happens when you switch between paradigms. By having fewer explicit things to manage, you lessen the scope of errors in naming those things. This is one reason why the DRY principle is advocated - the fewer times you type something, the fewer chances you have to typo it. Also you don't need the accessor function at all (and if at some point in the future you do want it you can make it a property). You don't have to invent separate names for each of the returned functions: the dot notation suddenly makes that a no brainer. Fair enough; you got two valid arguments there. Also the class is easier to extend: you no longer have to find and change every call to account() if you want to add another method: just add it. Of course, there are cases where you'll never want to extend it. Designing it in such a way that it's impossible to extend pretty much ensures that, doesn't it? I have no idea why someone who already has a working, object system would want to implement their own on top of closures. I'd even take issue with the idea that's it's a standard idiom for the quite uncommon task of creating object systems, it's a well known conceptual idea but it's not actually implemented as such very often. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Chris Mellon [EMAIL PROTECTED] writes: I have no idea why someone who already has a working, object system would want to implement their own on top of closures. This subthread is getting ridiculous -- closures are *not* useful only for implementing object systems! The object system thing is just a method of teaching abstractions popularized by SICP. Abstractions normally taken for granted, such as objects, or even expression evaluation, are implemented from scratch, using only the most basic primitives available. In a Lisp-like language with lexical scope, the most basic storage primitive is the lexical environment itself[1]. In real-life code, closures are used to implement callbacks with automatic access to their lexical environment without the need for the bogus additional void * argument one so often sees in C callbacks, and without communication through global variables. If the callbacks can access variables in the outer scope, it's only logical (and useful) for them to be able to change them. Prohibiting modification reduces the usefulness of closures and causes ugly workarounds such as the avar[0] pattern. If closures were useful only for implementing bogus object systems, neither they nor nonlocal would have made it to Python in the first place. [1] An illustration of that principle is an implementation of cons, the most primitive Lisp storage type, without the use of a higher-level storage object (such as a two-element vector): (defun cons (x y) (lambda (op) (if op x y))) (defun car (cons) (funcall cons t)) (defun cdr (cons) (funcall cons nil)) -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Hrvoje Niksic schrieb: Chris Mellon [EMAIL PROTECTED] writes: I have no idea why someone who already has a working, object system would want to implement their own on top of closures. This subthread is getting ridiculous -- closures are *not* useful only for implementing object systems! The object system thing is just a method of teaching abstractions popularized by SICP. Abstractions normally taken for granted, such as objects, or even expression evaluation, are implemented from scratch, using only the most basic primitives available. In a Lisp-like language with lexical scope, the most basic storage primitive is the lexical environment itself[1]. In real-life code, closures are used to implement callbacks with automatic access to their lexical environment without the need for the bogus additional void * argument one so often sees in C callbacks, and without communication through global variables. If the callbacks can access variables in the outer scope, it's only logical (and useful) for them to be able to change them. Prohibiting modification reduces the usefulness of closures and causes ugly workarounds such as the avar[0] pattern. If closures were useful only for implementing bogus object systems, neither they nor nonlocal would have made it to Python in the first place. There's a nice saying about this: The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said Master, I have heard that objects are a very good thing - is this true? Qc Na looked pityingly at his student and replied, Foolish pupil - objects are merely a poor man's closures. Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire Lambda: The Ultimate... series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress. On his next walk with Qc Na, Anton attempted to impress his master by saying Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures. Qc Na responded by hitting Anton with his stick, saying When will you learn? Closures are a poor man's object. At that moment, Anton became enlightened. http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html I do love closures, and I sometimes pitty python for not allowing to set outer scope variables. But then, it's because it lacks a variable declaration scheme (as e.g. javascript has), so _some_ design decision had to be made distinguishing variable declarations from pure references. And I can live with the consequences. Diez -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On 2007-10-29, Steven Bethard [EMAIL PROTECTED] wrote: Hrvoje Niksic wrote: Tommy Nordgren [EMAIL PROTECTED] writes: Given the following: def outer(arg) avar = '' def inner1(arg2) # How can I set 'avar' here ? I don't think you can, until Python 3: http://www.python.org/dev/peps/pep-3104/ But it definitely does work in Python 3 if you use 'nonlocal':: Python 3.0a1+ (py3k:58681, Oct 26 2007, 19:44:30) [MSC v.1310 32 bit (Intel)] on win32 Type help, copyright, credits or license for more information. def f(): ... x = 1 ... def g(): ... nonlocal x ... x = 2 ... print(x) ... g() ... print(x) ... f() 1 2 That said, I'd like to see the reason you think you want to do this. It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. def account(opening_balance): balance = opening_balance def get_balance(): nonlocal balance return balance def post_transaction(x): nonlocal balance balance += x return balance, post_transaction fred_balance, fred_post = account(1500) joe_balance, joe_post = account(12) fred_post(20) joe_post(-10) fred_balance() 1520 joe_balance() 2 Python classes will of course nearly always win, though the idiom looks like it might be faster (I don't have Python 3000 to try it out). -- Neil Cerutti It isn't pollution that is hurting the environment; it's the impurities in our air and water that are doing it. --Dan Quayle -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Neil Cerutti wrote: On 2007-10-29, Steven Bethard [EMAIL PROTECTED] wrote: Hrvoje Niksic wrote: Tommy Nordgren [EMAIL PROTECTED] writes: Given the following: def outer(arg) avar = '' def inner1(arg2) # How can I set 'avar' here ? I don't think you can, until Python 3: http://www.python.org/dev/peps/pep-3104/ But it definitely does work in Python 3 if you use 'nonlocal':: Python 3.0a1+ (py3k:58681, Oct 26 2007, 19:44:30) [MSC v.1310 32 bit (Intel)] on win32 Type help, copyright, credits or license for more information. def f(): ... x = 1 ... def g(): ... nonlocal x ... x = 2 ... print(x) ... g() ... print(x) ... f() 1 2 That said, I'd like to see the reason you think you want to do this. It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. Yeah, that's what I was afraid of. ;-) STeVe -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Neil Cerutti [EMAIL PROTECTED] wrote: It's allows a standard programming idiom which provides a primitive form of object oriented programming using closures to represent state. def account(opening_balance): balance = opening_balance def get_balance(): nonlocal balance return balance def post_transaction(x): nonlocal balance balance += x return balance, post_transaction fred_balance, fred_post = account(1500) joe_balance, joe_post = account(12) fred_post(20) joe_post(-10) fred_balance() TypeError: 'int' object is not callable 1520 joe_balance() TypeError: 'int' object is not callable 2 Python classes will of course nearly always win, though the idiom looks like it might be faster (I don't have Python 3000 to try it out). Python classes might be less error prone. I expect they could also be faster: accessing non-local variables (whether fetching or setting) has always been suprisingly slow in Python 2.x. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
brad a écrit : Tommy Nordgren wrote: def outer(avar=False): print avar if avar == True: return def inner(avar=True): print avar return avar outer(inner()) outer() This is not a general solution to this problem. Run my example code, it works (if I'm understanding your question correctly). It sets outer to True... inner returns True to outer and thus the var is set... am I missing something? Yes: you forgot to rebind avar in inner and check the result in outer. -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
On 29 okt 2007, at 21.59, brad wrote: Tommy Nordgren wrote: Given the following: def outer(arg) avar = '' def inner1(arg2) # How can I set 'avar' here ? Try this... works for me... maybe not for you? def outer(avar=False): print avar if avar == True: return def inner(avar=True): print avar return avar outer(inner()) outer() -- http://mail.python.org/mailman/listinfo/python-list This is not a general solution to this problem. What works, though, (I just thought of it) is to do the following: def outer(arg): adict = {} def inner1(arg): adict['avar'] = 'something' #now the value set by inner1 is available to other nested functions -- What is a woman that you forsake her, and the hearth fire and the home acre, to go with the old grey Widow Maker. --Kipling, harp song of the Dane women Tommy Nordgren [EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Tommy Nordgren [EMAIL PROTECTED] writes: Given the following: def outer(arg) avar = '' def inner1(arg2) # How can I set 'avar' here ? I don't think you can, until Python 3: http://www.python.org/dev/peps/pep-3104/ Currently the (ugly) solution is to change variable assignment to object mutation: def outer(arg) avar = [''] # use avar[0] where you'd normally use avar def inner1(arg2) # modify the value of avar by setting avar[0] -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Tommy Nordgren wrote: def outer(avar=False): print avar if avar == True: return def inner(avar=True): print avar return avar outer(inner()) outer() This is not a general solution to this problem. Run my example code, it works (if I'm understanding your question correctly). It sets outer to True... inner returns True to outer and thus the var is set... am I missing something? -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Tommy Nordgren wrote: Given the following: def outer(arg) avar = '' def inner1(arg2) # How can I set 'avar' here ? Try this... works for me... maybe not for you? def outer(avar=False): print avar if avar == True: return def inner(avar=True): print avar return avar outer(inner()) outer() -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Tommy Nordgren [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] | Given the following: | def outer(arg) | avar = '' | def inner1(arg2) | # How can I set 'avar' here ? You cannot at present. You can only mutate mutable outer vars: def outer(arg): avar = [''] def inner(argi): avar[0] = str(argi) ... -- http://mail.python.org/mailman/listinfo/python-list
Re: setting variables in outer functions
Hrvoje Niksic wrote: Tommy Nordgren [EMAIL PROTECTED] writes: Given the following: def outer(arg) avar = '' def inner1(arg2) # How can I set 'avar' here ? I don't think you can, until Python 3: http://www.python.org/dev/peps/pep-3104/ But it definitely does work in Python 3 if you use 'nonlocal':: Python 3.0a1+ (py3k:58681, Oct 26 2007, 19:44:30) [MSC v.1310 32 bit (Intel)] on win32 Type help, copyright, credits or license for more information. def f(): ... x = 1 ... def g(): ... nonlocal x ... x = 2 ... print(x) ... g() ... print(x) ... f() 1 2 That said, I'd like to see the reason you think you want to do this. STeVe -- http://mail.python.org/mailman/listinfo/python-list