Minimal built-ins (+ tiny doc suggestion)

Hi, Built-ins: In an effort to keep the core language as small as possible (to keep it "brain sized":-) would it be reasonable to deprecate filter() and map() and to move them to the standard library as happened with reduce()? After all, don't people mostly use list comprehensions and generator expressions for these nowadays? Docs: The Python Module Index http://docs.python.org/dev/py-modindex.html Shows _ | a | b | ... This is prettier than _ | A | B | ... but also harder to click because the letters are smaller; so I would prefer the use of capitals. -- Mark Summerfield, Qtrac Ltd, www.qtrac.eu C++, Python, Qt, PyQt - training and consultancy "Programming in Go" - ISBN 0321774639 http://www.qtrac.eu/gobook.html

Hi, Le 25/05/2012 09:53, Mark Summerfield a écrit :
Aside from the pain of porting existing code, what would this achieve? How do filter() and map() bother you if you can just ignore them and not use them? The only upside I can imagine in having less bultins is that using variables with the same names is a kind-of bad practice. But it can not cause a bug if you don’t use the builtin at all.
Adding CSS padding on links can make the clickable area bigger, so the choice of using capitals or not can be independent of that. Regards, -- Simon Sapin

On Fri, May 25, 2012 at 5:53 PM, Mark Summerfield <list@qtrac.plus.com> wrote:
I'd personally agree with filter() moving, but "map(str, seq)" still beats "(str(x) for x in seq)" by a substantial margin for me when it comes to quickly and cleanly encapsulating a common idiom such that it is easier both to read *and* write. The basic problem is that the answer to your question is "no" - for preexisting functions, a lot of people still use filter() and map(), with the comprehension forms reigning supreme only when someone would have had to otherwise use a lambda expression. We won the argument for moving reduce() to functools because it's such a pain to use correctly that it clearly qualified as an attractive nuisance. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Fri, 25 May 2012 19:09:29 +1000 Steven D'Aprano <steve@pearwood.info> wrote:
Only if you remember what the special value None does when passed to filter. The cognitive burden is higher. That said, the idea of moving filter() and map() away won't fly before at least Python 4. Regatds Antoine.

On Fri, May 25, 2012 at 2:09 AM, Steven D'Aprano <steve@pearwood.info> wrote:
And I think filter(bool, seq) beats the first. Exact same length, more explicit, one less key to press (Shift). The consistency of using comprehensions all the time has a certain attraction though. Cheers, Chris

On Fri, 25 May 2012 18:28:28 +1000 Nick Coghlan <ncoghlan@gmail.com> wrote:
Wasn't this changed discussed for that very reason as part of the move to 3.x? Which makes me wonder why reduce moved but not map and filter, when map and filter have obvious rewrites as list comprehensions, but reduce doesn't? Seems backwards to me.
Personally, I tend to favor list comprehensions most of the time (and I was a pretty heavy user of map and filter in the day), because it's just one less idiom to deal with. The exception is when they'd nest - I use [map(f, l) for l in list-of-lists] rather than nesting the comprehensions, because I then don't have to worry about untangling the nest. But I do agree that since they survived into 3.x, they need to stay put until 4.x. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/ Independent Software developer/SCM consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On Fri, May 25, 2012 at 9:29 AM, Mike Meyer <mwm@mired.org> wrote:
How quickly we forget. The point wasn't sparsity of constructs. The point was readability. Code written using map() or filter(), is usually quite readable -- excesses are possible, but not more so than using list comprehensions. However code that uses reduce() has a high likelihood of being unreadable, and is almost always rewritten more easily using a traditional for loop and some variables that are updated in the loop.
There are interesting considerations of readability either way. If you have to write a lambda to use map() or filter(), it is *always* better to use a list comprehension, because of the overhead in creating the stack frame for the lambda. But if you are mapping or filtering using an already-existing function, map()/filter() is more concise and I usually find it more readable, because you don't have to invent a loop control variable. My claim is that for the human reader (who is familiar with map/filter), it is less work for the brain to understand map(f, xs) than [f(x) for x in xs] -- there are more words to parse in the latter, and you have to check that it is the same 'x' in both places. The advantage of map/filter increases when f is a built-in function, since the loop implied by map/filter executes more quickly than the explicit loop (implemented using standard looping byte codes) used by list comprehensions. (I hesitate to emphasize the performance too much, since some hypothetical future Python implementation could make the performance the same in all cases. But with today's CPython, Jython and IronPython, it is important to know about relative performance of different constructs; and even PyPy doesn't alter the equation too much here. Still, the readability arguments aligns pretty much with the performance arguments, so they just strengthen each other.)
But I do agree that since they survived into 3.x, they need to stay put until 4.x.
And beyond. -- --Guido van Rossum (python.org/~guido)

Mark Summerfield wrote:
So you would put people through the pain of dealing with broken code and deprecation just so that people don't have to remember functions which you think they don't remember anyway? -1 Keeping the core language small is a benefit to core developers. It is not so much a benefit to users of the language -- if a programmer is only using the builtins, they are surely reinventing the wheel (and probably badly). To be an effective programmer, you surely are using functions and classes in the std lib as well as the builtins, which means you have to memorise both what the function is, *and* where it is. Shrinking the builtins while increasing the size of the std lib is not much of a human-memory optimization, and may very well be a pessimation. If you need a memory-jog, it is much easier to find builtins because they are always available to a quick call to dir(), while finding something in a module means searching the docs or the file system. -- Steven

Hi, Le 25/05/2012 09:53, Mark Summerfield a écrit :
Aside from the pain of porting existing code, what would this achieve? How do filter() and map() bother you if you can just ignore them and not use them? The only upside I can imagine in having less bultins is that using variables with the same names is a kind-of bad practice. But it can not cause a bug if you don’t use the builtin at all.
Adding CSS padding on links can make the clickable area bigger, so the choice of using capitals or not can be independent of that. Regards, -- Simon Sapin

On Fri, May 25, 2012 at 5:53 PM, Mark Summerfield <list@qtrac.plus.com> wrote:
I'd personally agree with filter() moving, but "map(str, seq)" still beats "(str(x) for x in seq)" by a substantial margin for me when it comes to quickly and cleanly encapsulating a common idiom such that it is easier both to read *and* write. The basic problem is that the answer to your question is "no" - for preexisting functions, a lot of people still use filter() and map(), with the comprehension forms reigning supreme only when someone would have had to otherwise use a lambda expression. We won the argument for moving reduce() to functools because it's such a pain to use correctly that it clearly qualified as an attractive nuisance. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Fri, 25 May 2012 19:09:29 +1000 Steven D'Aprano <steve@pearwood.info> wrote:
Only if you remember what the special value None does when passed to filter. The cognitive burden is higher. That said, the idea of moving filter() and map() away won't fly before at least Python 4. Regatds Antoine.

On Fri, May 25, 2012 at 2:09 AM, Steven D'Aprano <steve@pearwood.info> wrote:
And I think filter(bool, seq) beats the first. Exact same length, more explicit, one less key to press (Shift). The consistency of using comprehensions all the time has a certain attraction though. Cheers, Chris

On Fri, 25 May 2012 18:28:28 +1000 Nick Coghlan <ncoghlan@gmail.com> wrote:
Wasn't this changed discussed for that very reason as part of the move to 3.x? Which makes me wonder why reduce moved but not map and filter, when map and filter have obvious rewrites as list comprehensions, but reduce doesn't? Seems backwards to me.
Personally, I tend to favor list comprehensions most of the time (and I was a pretty heavy user of map and filter in the day), because it's just one less idiom to deal with. The exception is when they'd nest - I use [map(f, l) for l in list-of-lists] rather than nesting the comprehensions, because I then don't have to worry about untangling the nest. But I do agree that since they survived into 3.x, they need to stay put until 4.x. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/ Independent Software developer/SCM consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

On Fri, May 25, 2012 at 9:29 AM, Mike Meyer <mwm@mired.org> wrote:
How quickly we forget. The point wasn't sparsity of constructs. The point was readability. Code written using map() or filter(), is usually quite readable -- excesses are possible, but not more so than using list comprehensions. However code that uses reduce() has a high likelihood of being unreadable, and is almost always rewritten more easily using a traditional for loop and some variables that are updated in the loop.
There are interesting considerations of readability either way. If you have to write a lambda to use map() or filter(), it is *always* better to use a list comprehension, because of the overhead in creating the stack frame for the lambda. But if you are mapping or filtering using an already-existing function, map()/filter() is more concise and I usually find it more readable, because you don't have to invent a loop control variable. My claim is that for the human reader (who is familiar with map/filter), it is less work for the brain to understand map(f, xs) than [f(x) for x in xs] -- there are more words to parse in the latter, and you have to check that it is the same 'x' in both places. The advantage of map/filter increases when f is a built-in function, since the loop implied by map/filter executes more quickly than the explicit loop (implemented using standard looping byte codes) used by list comprehensions. (I hesitate to emphasize the performance too much, since some hypothetical future Python implementation could make the performance the same in all cases. But with today's CPython, Jython and IronPython, it is important to know about relative performance of different constructs; and even PyPy doesn't alter the equation too much here. Still, the readability arguments aligns pretty much with the performance arguments, so they just strengthen each other.)
But I do agree that since they survived into 3.x, they need to stay put until 4.x.
And beyond. -- --Guido van Rossum (python.org/~guido)

Mark Summerfield wrote:
So you would put people through the pain of dealing with broken code and deprecation just so that people don't have to remember functions which you think they don't remember anyway? -1 Keeping the core language small is a benefit to core developers. It is not so much a benefit to users of the language -- if a programmer is only using the builtins, they are surely reinventing the wheel (and probably badly). To be an effective programmer, you surely are using functions and classes in the std lib as well as the builtins, which means you have to memorise both what the function is, *and* where it is. Shrinking the builtins while increasing the size of the std lib is not much of a human-memory optimization, and may very well be a pessimation. If you need a memory-jog, it is much easier to find builtins because they are always available to a quick call to dir(), while finding something in a module means searching the docs or the file system. -- Steven
participants (8)
-
Antoine Pitrou
-
Chris Rebert
-
Guido van Rossum
-
Mark Summerfield
-
Mike Meyer
-
Nick Coghlan
-
Simon Sapin
-
Steven D'Aprano