Live data from Hacker News

Functional programming with Python

ua.pycon.org

1–10 of 51 posts

Re: Functional programming with Python

#4
Forgot one big con: Python lambda functions aren't "proper" functions (ie. arbitrary multi-line code blocks). Guido van Rossum has addressed this many times, saying (in effect) "it adds undue complexity and would be un-Pythonic", eg:

http://www.artima.com/weblogs/viewpost.jsp?thread=147358

This is one of my (very few!) gripes with FP in Python.

Re: Functional programming with Python

#5
I'm curious, on the Currying (Standard Library) slide, the author uses `attrgetter` from the `operator` module -- I've always used `getattr` to achieve the same thing. Am I missing something by not using `attrgetter`?

Re: Functional programming with Python

#6
post #4

Forgot one big con: Python lambda functions aren't "proper" functions (ie. arbitrary multi-line code blocks). Guido van Rossum has addressed this many times, saying (in effect) "it adds undue complexity and would be un-Pythonic", eg: http://www.artima.com/weblogs/viewpost.jsp?thread=147358 This is one of my (very few!) gripes with FP in Python.

I don't know if this is a problem if you're going hardcore with your FP -- one line is one expression, and multiple expressions are probably going to be stateful, which should probably be factored out into something with a name.

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.

Re: Functional programming with Python

#7
post #6
post #4

Forgot one big con: Python lambda functions aren't "proper" functions (ie. arbitrary multi-line code blocks). Guido van Rossum has addressed this many times, saying (in effect) "it adds undue complexity and would be un-Pythonic", eg: http://www.artima.com/weblogs/viewpost.jsp?thread=147358 This is one of my (very few!) gripes with FP in Python.

I don't know if this is a problem if you're going hardcore with your FP -- one line is one expression, and multiple expressions are probably going to be stateful, which should probably be factored out into something with a name. 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…

...or anywhere you're using a 'let' statement. I write a lot of OCaml, and I write a lot of multi-line anonymous functions that aren't stateful. I think it's less common to do this in Haskell, but that's more because it's Haskell than because there aren't any side effects.

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).

Re: Functional programming with Python

#8
i started learning functional programming with python, it falls apart at ~300 loc which is absurdly low, which makes python basically useless for production FP.

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 [1].

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.

[1] http://news.ycombinator.com/item?id=3962316

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.

[2] implement generators without yield http://www.dustingetz.com/2012/10/03/implement-python-genera...

[3] easy monads http://www.dustingetz.com/2012/10/07/monads-in-python-identi...

[4] hard monads http://www.dustingetz.com/2012/10/02/reader-writer-state-mon...

[5] peter norvig's Lispy refactored using monads https://github.com/dustingetz/monadic-interpreter

Re: Functional programming with Python

#9
post #4

Forgot one big con: Python lambda functions aren't "proper" functions (ie. arbitrary multi-line code blocks). Guido van Rossum has addressed this many times, saying (in effect) "it adds undue complexity and would be un-Pythonic", eg: http://www.artima.com/weblogs/viewpost.jsp?thread=147358 This is one of my (very few!) gripes with FP in Python.

And you can't pass them as simple functions to do stuff via the multiprocessing module because they can't be pickled. I don't understand this infatuation with FP in Python. To me the essence of functional programming is immutable state. Python has mutable state to the core. List comprehensions are novel syntax for many FP-esque operations (so much so that map, reduce, & filter were almost removed from Python at some point) yet, to their core they're full of mutable-state disgustingness. For example:

    >>> a = range(12)
    >>> [a.pop(i) for i in range(3)]
    [0, 2, 4]
    >>> a
    [1, 3, 5, 6, 7, 8, 9, 10, 11]
As long as list methods have methods that change state of the object, even when processing said object, Python handles FP at a very superficial syntactic level.

Re: Functional programming with Python

#10
post #5

I'm curious, on the Currying (Standard Library) slide, the author uses `attrgetter` from the `operator` module -- I've always used `getattr` to achieve the same thing. Am I missing something by not using `attrgetter`?

Short answer: not really.

Long answer:

  In [1]: from operator import attrgetter

  In [2]: class Person:
     ...:     def __init__(self, name):
     ...:         self.name = name
     ...:         

  In [3]: me = Person('walrus')

  In [4]: getattr(me, 'name')
  Out[4]: 'walrus'

  In [5]: attrgetter('name')(me)
  Out[5]: 'walrus'
This is potentially useful if you're using `map`:

  In [6]: people = [me, Person('aschwo')]

  In [7]: list(map(lambda obj: getattr(obj, 'name'), people))
  Out[7]: ['walrus', 'aschwo']

  In [8]: list(map(attrgetter('name'), people))
  Out[8]: ['walrus', 'aschwo']
Really, though, the functional programming idioms don't meld too well with Python. I think this is a lot nicer:

  In [9]: [person.name for person in people]
  Out[9]: ['walrus', 'aschwo']
Post reply on HN