Hacker News new | ask | show | jobs
by metalliqaz 2895 days ago
This comment puzzles me. For one, I can't recall meeting a stong FP proponent that accepts anything less than a language designed from the ground-up to be true FP. Second, how is Python afraid of FP? This[1] document has been part of the Python docs for as long as I can remember.

[1] https://docs.python.org/2/howto/functional.html

4 comments

There has been some pushback on the inclusion of common functional idioms in Python, though. For example, GvR has expressed regret about allowing map, filter, etc. into Python, on the grounds that comprehensions are a more Pythonic way to accomplish most of the same stuff.
I assume it's because of this...

Zen of Python: There should be one-- and preferably only one --obvious way to do it.

True, but, if it were just that, I would expect Python to only have the map, filter, etc. functions, which have been in there since 1.0. List comprehensions were introduced much later, in version 2.

That makes comprehensions the 2nd way to do it. They're also less obvious in my book, since their readability tends to drop precipitously once you start adding multiple "for" clauses to one.

But comprehensions are also a functional idiom.
Yeah, sorry, I didn't mean to say that Python's not functional without a "map" function. More trying to guess where that perception comes from. Python's comprehensions are (I believe) inspired by Haskell, but, if you're not a Haskeller, you're probably more used to other ways of doing things.
The version Python has is awkward to work with, to the point that many Haskell programmers don't even realise it exists. The "do notation" style is much clearer than the "comprehension" style; unfortunately Python has no equivalent.
FP means referential transparency. For-comprehensions operate on iterators and iterators are not FP, being a very dirty and mutable protocol.

Do not confuse FP with declarative programming or with laziness. FP often implies declarative APIs and laziness but not vice-versa.

Python's comprehensions were lifted from Haskell, and its map and filter functions also operate on iterables. They can't be purely functional because of the surrounding language, but they do follow a functional style.

(expr for item in iterable if cond) is more or less another way to spell map(lambda item: expr, filter(lambda item: cond, iterable)), except readable.

You could define "functional programming" to absolutely require referential transparency, but that's not what the rest of the thread is doing.

I don't mean to be pedantic but IIRC Python's comprehensions actually came from the SETL language.

Obviously it's ultimately the same thing either way, but that's the lineage (SETL -> ABC -> Python).

https://en.wikipedia.org/wiki/SETL

I didn't know about SETL, that's interesting.

https://docs.python.org/3/howto/functional.html#generator-ex... claims Python borrowed them from Haskell, but the ABC link seems more likely.

Aren't map and filter just redundant if you accept list comprehension as Pythonic thing to do?
Maybe just map and filter but there are far more operations that can be done on these types than what is cleanly expressed in a comprehension.
Some people think, because python is not fully embracing functional programming, it must fear it. Because anything less than 100% functional is not good enough. Namly the limited lambdas are always brought as a reason.
Most lisps are multiparadigm, and few would claim lisps are anti FP.

I think Python is considered anti FP for two reasons: when suggestions to add more FP features have been raised, Guido has fairly unambiguously rejected those features.

That’s all fine though. Python can do what Python wants. All else being equal, I’d prefer a little more functional flavor than Python has, but I won’t turn my nose up at writing Python if duty calls.

Many programming languages these days have FP tendencies.

However I can barely think of another mainstream and high level language that is more anti-FP than Python.

And lambdas, in spite of popular opinion, have nothing to do with it ;-)

(Actually I can think of another language that is more anti-FP than Python and that would be Go ... people saying Go is “pythonic” have it right)

I'd be curious which of JavaScript, perl, js, and Ruby (and hell, go or Java, which are often considered high level) is more friendly to fp than python, and why, obviously. That's pretty much every other mainstream high level language ;)

I've never heard anyone call go pythonic.

> I'd be curious which of JavaScript, perl, js, and Ruby (and hell, go or Java, which are often considered high level) is more friendly to fp than python, and why, obviously.

JS (which you listed twice), Perl (5 or 6), and in some ways Ruby (which is a mixed bag, because it doesn't actually have functions per se, but even so is in many ways more friendly to functional style than Python.)

Being expression-oriented languages with full support for anonymous functions (callables in Ruby) and non-awkward creation of full (rather than read-only) closures are the main common factors.

Sorry, php, not js the second time.

I'm not sure what you mean by read only closures, unless you mean a close which can later modify the enclosing scope, which python supports via the nonlocal keyword but also is decidedly bad, and not something I've ever before heard of as an fp concept.

And as far as I can tell, your entire argument reduces to better lambdas. Which is what you said it wouldn't be. I feel misled. Oh wait you're a different user. Still this point stands. I wouldn't have responded if the expected answer was "better lambdas". You can do better.

I guess the next important question is "what are the things you feel make a language functional, and why are those things valuable"?

There are lots of aspects of functional programming that are good, I personally agree that anonymous functions are not one of them, especially when you have no need for callbacks (python doesn't really).

And it's very possible to write functional code, imo, without anonymous functions. Why do you disagree.

Ruby has multi line lambdas and code blocks. Python doesn't. However we can't pass a function as argument (actually a method but it could be a def in a module). We can pass a symbol with the name of the fuction. We can pass the function in Python.

I write very few classes in Python. I tend to write modules and import them. It's what I do in Elixir, obviously.

However I don't write much Ruby code outside Rails and Rails is definitely object oriented and directs the developer to write OO code. Instead the most popular web framework for Python, Django, is almost anarchy, anything will do.

> However we can't pass a function as argument

Right, Ruby doesn't have functions at all, so you can't pass them. This is why Ruby isn't simply better than Python here, though I'd say it's still mostly better.

> We can pass a symbol with the name of the fuction.

No, you can either convert the name to a callable and pass that, or for some methods you can pass the name of a method you'd like called on an object that the called method will get somewhere else. This isn’t esuivslent to having the name of a function. Instead, its a facility that is usually offered by a method to provide a more concise alternative to passing an equivalent block for a no-arg method. E.g.:

  enum.inject(start, :foo)
is equivalent to:

  enum.inject(start) { |obj| obj.send(:foo) }
If you actually have a function-like (callable) object (bound method object or proc/lambda) you can send that as a regular argument, or if the method it is passed to expects a block (as is more frequently the case for Ruby methods that need a single function-like argument) convert the callable to a block with the “&” prefix and send that.
I’m not a strong FP proponent per se. I just really enjoy using things like Java 8 Streams, Lodash/Ramda, etc. Comprehensions are nice but they have a more limited scope than functions. Honestly the same can be said for decorators. Useful, but ultimately not much more useful than a plain old higher order function.
I love functional style and I think Python is very friendly to that style. You can make pure functions. You can use classes as store of values. Pass values and functions around as they are first class citizens.

That you need some local state to implement a pure function isn't a problem as you can limit it to very simple things. Anonymous functions are not something you need either, just give it a name and pass it, wtp?

I agree most of the "Python is not functional enough" criticism comes from people who just want as pure FP as possible.