reduce(operator.add, map(len, ss))
sum(len(s) for s in ss)
def square_sum(a, b):
return sum(map(lambda x: x**2, range(a, b+1)))
def square_sum(a, b):
return sum(x**2 for x in range(a, b+1))
For stuff like functools.partial, in simple cases, isn't it clearer to just write this?
Also: namedtuple is great instead of "using classes as attribute containers".
$ python -m timeit 'import string;from operator import itemgetter;[itemgetter('slice') for x in string.letters]'
100000 loops, best of 3: 14.2 usec per loop
$ python -m timeit 'import string;from operator import itemgetter;[lambda x: x.slice for x in string.letters]'
100000 loops, best of 3: 10.4 usec per loop
Er, OK. Just don't look at the implementation. Cannot be unseen.
python -m timeit 'import string;from operator import itemgetter; getter=itemgetter('slice'); [getter(x) for x in string.letters]'
>python -m timeit -s "from operator import itemgetter; elem0 = itemgetter(0)" "elem0('s')"
10000000 loops, best of 3: 0.095 usec per loop
>python -m timeit -s "from operator import itemgetter; elem0 = lambda x: x" "elem0('s')"
10000000 loops, best of 3: 0.138 usec per loop
It's true that Python will use a list comprehension or a generator expression where you would normally do this, but Python 3 still includes map() and filter(). (Despite Guido not being a big fan of these functions - http://www.artima.com/weblogs/viewpost.jsp?thread=98196).
My point is simply that the presentation does a good job at exposing what FP is and how to implement it in Python. Moving from maps to comprehensions comes naturally, once you get the hang of the idea.
PS: I have the same question about functools.partial. Can somebody answer this?
Regarding to debug function and partial function application, - it depends. As for me
debug = partial(log, "debug")
python's data structures are mutable, and mutable data structures necessarily expose a different interface than immutable data structures. using mutable datastructures in immutable style necessarily has severe performance penalties; and to do meaningful stuff you need to use a statement, and you can't put a statement in a python lambda. And Guido thinks lambda's are un-pythonic and a misfeature which he seems to regret .
python is a great sandbox for imperative programmers interested in FP, and these are great slides. it's awesome to play with these concepts in a familiar language - thats how i started - but its important to note that FP is just not pythonic, and thus it's probably a mistake to put functional-style python into production.
if you are interested in functional python, i wrote about it a bit this year in my blog, because despite all this, python is a nice language for evangelism aimed at imperative developers.
 implement generators without yield http://www.dustingetz.com/2012/10/03/implement-python-genera...
 easy monads http://www.dustingetz.com/2012/10/07/monads-in-python-identi...
 hard monads http://www.dustingetz.com/2012/10/02/reader-writer-state-mon...
 peter norvig's Lispy refactored using monads https://github.com/dustingetz/monadic-interpreter
This is one of my (very few!) gripes with FP in Python.
>>> a = range(12)
>>> [a.pop(i) for i in range(3)]
[0, 2, 4]
[1, 3, 5, 6, 7, 8, 9, 10, 11]
>>> a = tuple(3*x for x in range(5))
>>> map(lambda x: str(x), a) #can be iterated
['0', '3', '6', '9', '12']
>>> a = 9
TypeError: 'tuple' object does not support item assignment
AttributeError: 'tuple' object has no attribute 'pop'
In Haskell, the only places (that occur to me right now) where you'll have multiple lines are:
* Pattern matching function arguments
* Giving things names with `let` or `where`
* In a monadic `do` block, which is just sugar that reduces to single-expression chain of lambdas
And all of these are language design decisions that require more than just multi-statement lambdas.
Random other tidbit that doesn't deserve its own comment:
In Python, instance.method is the same as doing ClassName.method(instance). This can be helpful when using map/filter, because you get to do map(ClassName.method,lst) instead of map(lambda x: x.method,lst).
I don't know if this is a problem if you're going hardcore with your FP. When we're talking about "lines" in Python, one line is exactly one statement, and if you're doing FP, that statement is an expression. Multiple statements are going to be either stateful, or declaring a temporary name for an intermediate value.
I am probably not being sufficiently imaginative right now, but I can't think of any fully-fledged functional pattern which would require multiple statements in a lambda, which would not be better abstracted out and given a name, and I would genuinely like to hear some examples of cases where a multi-statement lambda make for "better" code (or to hear how my presentation of this problem might be flawed, because I haven't done any serious Python programming recently enough to be very close to the issue).
In Haskell, a language where the syntax has been exhaustively designed to facilitate FP, the only places where you'll see multiple lines (I'm pretty sure this is exhaustive, without using GHC extensions, eg. Arrow `proc` blocks) are:
* In a monadic `do` block -- which is just sugar that reduces to single-expression chain of lambdas, and are not equivalent to multi-statement lambdas
But in the process of translating a comment I wrote in another forum from Ruby to Python, it became apparent that, as long as it's pythonic to implement `__add__` for any monoidal type, the resulting polymorphic `sum`, together with list comprehensions, will cover pretty much everything.
So I'm actually coming around to Guido's side here.
 Assuming there's a consistent __mul__/product for alternative monoid instances, and with `all` and `any` to handle numerically-cast booleans.
I think you were right the first time; removing reduce from Python is very lame.
I don't have the math to back this up, so please correct me if you know otherwise (and especially if you can demonstrate otherwise, though I know this being wrong is not contingent on that), but: I'm pretty sure `mconcat` with a `map` (or a list comprehension) is exactly as general as `fold`.
> Plus, unless you implement something akin to newtype wrappers for alternative monoid instances (hardly Pythonic), you're going to be restricted to a single foldable function for any given type.
Again, I know this isn't an argument and demonstrates shitty memory on my part, but a single solid example here would be key to me understanding this debate:
What is an example of a type with more than 2 monoids on it, whose fold could not be cleanly expressed with a sum/product and a map/comprehension, which is not already included in the standard library (any/all/gcd/lcm/max/min)?
[I suspect there either won't be an easy answer, or it will be so basic that I'll be brutally embarrassed... this is all kinda talking out of my ass, I have no exposure to category theory outside of reading haskell papers]
Maybe I'm being obtuse, but I don't quite understand what you mean when you say "mconcat with a map". But to see why mconcat isn't as general as a fold, you need only to take a look at the types:
mconcat :: Monoid a => [a] -> a
foldl :: (a -> b -> a) -> a -> [b] -> a
mconcat can be implemented in terms of a fold, e.g.
mconcat = foldl mappend mempty
There are plenty of uses for folds that don't involve monoids, and therefore can't be implemented with mconcat plus a Monoid instance. As a trivial example, take
Prelude> foldl (/) 400 [4, 4, 5]
Associativity notwithstanding, it's also not adequate to say that 2 monoid instances should be enough for any type. Maybe that is true in some or even most cases, but it is certainly not true in the general case. Haskell has newtypes to mitigate this problem, essentially enabling an arbitrary number of Monoid instances to be defined per type, but Python only lets you write one __add__ and one __mul__ for a given class. On top of that, I don't believe Python even has a product function that folds __mul__ over a list the way sum folds __add__, so really the limit is 1, not 2.
Anyway it's all moot because, as someone pointed out, reduce hasn't been removed from Python, just relegated to a library. :) I think it's a fundamental enough operation that it should be built in, but obviously Guido and I have differing opinions on FP.
> We already have sum(); I'd happily trade reduce() for product(), so that takes care of the two most common uses.
product() never made it in as a builtin; anyone know why?
Now if you don't want to type the code every time, that's fine: use collections.namedtuple.
A little mistake on page 48: the Clojure code will fail.
(map #(* % 2) '(1 2 3))
(map (partial * 2) '(1 2 3))
(map #(%*2) '(1 2 3))
It's a work in progress, and I often think to myself, "Is this a good idea".
Here's the latest iteration: I'm in the middle of documenting things for an alpha release:
In : from operator import attrgetter
In : class Person:
...: def __init__(self, name):
...: self.name = name
In : me = Person('walrus')
In : getattr(me, 'name')
In : attrgetter('name')(me)
In : people = [me, Person('aschwo')]
In : list(map(lambda obj: getattr(obj, 'name'), people))
Out: ['walrus', 'aschwo']
In : list(map(attrgetter('name'), people))
Out: ['walrus', 'aschwo']
In : [person.name for person in people]
Out: ['walrus', 'aschwo']
PS: map returns a list, no need to call list() on it.
In : sq = lambda x: x * x
In : map(sq, [1,2,3,4])
Out: <builtins.map at 0x2135050>
In : list(_)
Out: [1, 4, 9, 16]
f = attrgetter("some_property")
f = lambda obj: getattr(obj, "some_property")
I wish I had the speaker to give a little more with each slide though.