That said, it looks a lot more pleasant than Python. The addition of pattern matching alone makes this seem like a very worthwhile project, a big improvement on Python.
That said, it looks a lot more pleasant than Python. The addition of pattern matching alone makes this seem like a very worthwhile project, a big improvement on Python.
def reduce(enumerable, fun) do
result =
Enumerable.reduce(enumerable, {:cont, :first}, fn
x, :first -> {:cont, {:acc, x}}
x, {:acc, acc} -> {:cont, {:acc, fun.(x, acc)}}
end)
|> elem(1)
case result do
:first -> raise Enum.EmptyError
{:acc, acc} -> acc
end
end
Seems pretty straightforward to me.https://github.com/elixir-lang/elixir/blob/v1.7.4/lib/elixir...
(define (reduce-left fn init lst)
(if (null? lst)
init
(reduce-left fn (fn init (car lst)) (cdr lst))))
It's clear from that quote that Guido (at least at that time) doesn't have real experience with functional programming and is letting his personal biases cloud his judgement.Okay maybe '"scheme isn't a functional language because it allows side effects and only Haskell and family are allowed to call themselves functional", or whatever. He seems to perhaps hint at that mentality. But the fact remains that a language like scheme makes this much easier than python.
foldl _ acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs
And in Python something like def foldl(f, acc, l):
for x in l:
acc = f(acc, x)
return acc
Which doesn't seem much harder to read or write than any other version, to me (it's all just syntax around the same algorithm).In fact Python taught a generation of programmers to love functional code, because of the big speedup available from stringing together C-native builtins with higher order functions.
Furthermore over the years Guido has made it pretty clear that he doesn't particularly like or care about functional programming: https://python-history.blogspot.com/2009/04/origins-of-pytho...
I've actually started wishing for the opposite change in my use of Clojure. There, it is currently optional to supply a name for the fn form. Always supplying the name, like in "(fn add-42 [x] (+ x 42))", would make stack traces more readable and the named function object would be easy to identify when it appeared in the REPL / pretty-printed data structures.
Not being able to define a two-line function in the place where it's used because you have to give it a name discourages FP in a way many other modern languages do not.
def something(x):
def myfunc(y, z):
...
return result
reduce(myfunc, x)
So the difference is like having to write x = some_very_complex_expression_that_can_get_quite_long
some_function(x)
instead of some_function(some_very_complex_expression_that_can_get_quite_long)
In many cases this may make code even more readable.I'm not saying that Python's lambdas are perfect as they are or that multi-line lambdas would be a bad thing. I'm just saying it's not as bad as you paint it.
'More readable' is subjective. It's clear that Guido and much of the Python community believe that FP is less readable, less pythonic, and that viewpoint is exactly the sort of hostility towards FP that I'm talking about. And in no small part this is a self-fulfilling attitude, e.g. "python lambdas are ugly because pythonistas believe FP is ugly." They're way uglier in python than in other languages. The ugliness of python's lambda is a trait of python, not a trait of FP, yet it's ugliness cited to justify itself.
> when a for loop would be faster
Hey, that's fine. But I think much of the time for the sort of things I'm working on, that's deep into "premature optimization" territory. I'd rather a slight linear slowdown with more readable code than a slight linear speedup with less readable code. I'd prefer that python not "subtly discourage" me to nudge me towards less readable code because a list comprehension is marginally more performant.
Generators also get you another FP checkbox because you now have laziness in a very accessible form. You get building blocks like infinite sequences and so on. And you have access to all the normal primitives like reduce, take, partial, groupby etc in the itertools/functools std modules.