views:

180

answers:

2

I have have read several entries regarding dropping several functional functions from future python, including map and reduce.

What is the official policy regarding functional extensions?
is lambda function going to stay?

+10  A: 

Well, Python 3.0 and 3.1 are already released, so you can check this out for yourself. The end result was that map and filter were kept as built-ins, and lambda was also kept. The only change was that reduce was moved to the functools module; you just need to do

from functools import reduce

to use it.

Future 3.x releases can be expected to remain backwards-compatible with 3.0 and 3.1 in this respect.

Latest 3.x docs: http://docs.python.org/dev/py3k/
Roger Pate
Attention to the "check this out for yourself" part: installing python 3.1 along 2.6 int he same system is rather painless, and you can easily have both. If you are on Linux and have no python3 packages, you can download the source and build python3.1 in under 10 minutes.
jsbueno
+1  A: 

In Python 3.x, Python continues to have a rich set of functional-ish tools built in: list comprehensions, generator expressions, iterators and generators, and functions like any() and all() that have short-circuit evaluation wherever possible.

Python's "Benevolent Dictator For Life" floated the idea of removing map() because you can trivially reproduce its effects with a list comprehension:

lst2 = map(foo, lst)

lst3 = [foo(x) for x in lst]

lst2 == lst3  # evaluates True

Python's lambda feature has not been removed or renamed, and likely never will be. However, it will likely never become more powerful, either. Python's lambda is restricted to a single expression; it cannot include statements and it cannot include multiple lines of Python code.

Python's plain-old-standard def defines a function object, which can be passed around just as easily as a lambda object. You can even unbind the name of the function after you define it, if you really want to do so.

Example:

# NOT LEGAL PYTHON
lst2 = map(lambda x: if foo(x): x**2; else: x, lst)

# perfectly legal Python
def lambda_function(x):
    if foo(x):
        return x**2
    else:
        return x

lst2 = map(lambda_function, lst)

del(lambda_function) # can unbind the name if you wish

In short, Python has lost none of its functional power. There is some general feeling that list comprehensions and generator expressions are probably preferable to map(); in particular, generator expressions can sometimes be used to do the equivalent of a map() but without allocating a list and then freeing it again. For example:

total = sum(map(lst, foo))

total2 = sum(foo(x) for x in lst)

total == total2  # evaluates True

The map() allocates a new list, which is summed and immediately freed. The generator expression gets the values one at a time and never ties up the memory of a whole list of values.

steveha
map() in Py3 returns a generator, not a list.
Paul McGuire
@Paul: thank you for that. Given how everything but `list()` returns an iterator or a generator now, I should have expected that!
steveha
@steveha: the eventual list of changes for Py3 was such a moving target for so long, important changes that were added late in the game could easily be overlooked (like a completely incompatible exception catching syntax! I know, Py3 was not intended to be code-breakage-free, but save this single improvement, I could have had a single pyparsing source base for both Py2 and Py3, without any auto-conversion sleight of hand. Do I sound bitter? That would be because of my bitterness.).
Paul McGuire
@Paul, I sympathize. I recently wrote a module, for fun, that I wanted to work in any version of Python from 1.5 on. I discovered that Python < 3 choked on Python 3 syntax and Python 3 chokes on some Python < 3 syntax; that exception syntax was the killer. I was able to work around every other issue, but I couldn't get past that exception syntax. In the end, I made each version of the function a triple-quoted string, and used `exec()` to compile the appropriate version for whatever Python you use to run the code. That's an ugly hack. :-(
steveha
@steveha: all is not lost, there is a form of exception catching that is Py2 AND Py3 compliant, but it requires a function call to sys.exc_info, which is a 15-20% perf penalty for me in pyparsing. If you can stand it, do this: `except Exceptiontype: excvar = sys.exc_info()[1]` is the same as `except ExceptionType, excvar:` in Py2 and `except ExceptionType as excvar:` in Py3.
Paul McGuire
@Paul, I think the real way to do it is just to have two parallel versions of your source code, and decide which one to use based on the Python version. You could always add `#ifdef` statements to your master Python source code, and use the C preprocessor to make the two parallel versions from a single, unified source file. If you are going to support Python 2.x and Python 3.x, that is probably the least-painful way. Heck, you could even make macros to expand into correct-syntax `except` statements!
steveha
@steveha: Using CPP sounds insane. 2to3 recommends maintaining only one copy of the code, in Python 2.6, and using 2to3 to release Python 3 code.
kaizer.se
@Paul, they said I was mad, I'll show them, I'll show them all, ha ha HAHAHA! (Sorry) Yeah, using 2to3 makes a lot more sense than using CPP. :-)
steveha