7 ms·
Functional programming in Python is severely hampererd by Python's lambda keyword, which - simply put - sucks.
by seertaak 6y ago
Functional programming in Python is severely hampererd by Python's lambda keyword, which - simply put - sucks.
- 0x2c8 6y agoCan you elaborate on this? What is wrong with Python's `lambda`?
- kissgyorgy 6y agoIt can only have one line for example.
- Iwan-Zotow 6y agono, not correct
- pansa2 6y agoPython’s `lambda` can only contain a single expression. There’s no good way to add support for full anonymous functions to Python’s grammar. One of the rules that makes significant-whitespace work elegantly is that statements can contain expressions, but never vice-versa.
- omaranto 6y agoPlenty of languages with significant-whitespace have multiline anonymous functions, like Haskell, Standard ML, Ocaml, etc. Maybe it's no possible in Python for a student reason, but the reason is not that the syntax is bad on indentation.
- pansa2 6y agoThe syntaxes of those languages are fundamentally different from Python’s. They don’t have an “expressions may not contain statements” rule - they don’t even have statements.
- omaranto 6y agoIt sounds like you agree with me: the reason Python does not have multiline lambdas is not that it has significant-whitespace, but other decisions including the “expressions may not contain statements” rule.
- c-cube 6y agoNitpick : neither ocaml nor SML have significant whitespace.
- omaranto 6y agoYou're right! It's been too long since I used them. I think I was probably remembering F#'s light syntax.
- ausjke 6y agosince lambda is for simple and short anonymous functions most of the time why do I need type the whole word each time? can they also do what javascript does(or similar): x => x * 2 instead of lambda x : x * 2
- rustyminnow 6y agoLike others have said: - Can only have one line - Can only use expressions, not statements. E.g. `print`s, loops, conditionals are out. - Overall just kinda clunky Here's an SO post about lambdas where the answer is "Use def instead." https://stackoverflow.com/questions/14843777/how-to-write-python-lambda-with-multiple-lines https://stackoverflow.com/questions/14843777/how-to-write-py...
- bobbylarrybobby 6y agoThe lambda calculus is Turing complete, so in theory, Python’s lambdas should suffice...
- rustyminnow 6y agoI mean... You're right. They suffice. They're just less friendly (i.e. useful) than lambdas in other languages.
- zelphirkalt 6y agoWhich of course says nothing about usability and readability.
- jolux 6y agoTuring completeness is completely unrelated to whether or not anonymous functions are easy to use in Python.
- heavyset_go 6y agoprint() is a function now and you can use it with lambdas.
- pmiller2 6y agoEven in Python 2, you can do something like this: println = lambda s: sys.stdout.write(s + '\n') Not that it really makes things much better, but, at least it shows you can do it.
- 6y ago
- VWWHFSfQ 6y agoThe use of lambda is becoming somewhat of a smell in Python in general. PSF's own black code formatter will complain about using it and pretty much always says to just use a def instead
- AlexCoventry 6y agoAlso by the lack of persistent data structures with structural sharing. That forces you to take an expensive copy whenever you want a modified version of some data, or bash it in place.
- Iwan-Zotow 6y agoIsn't it a true functional way?
- iimblack 6y agoI could definitely be wrong but I think most functional data structures aren’t fully copied. Instead, they’ll utilize something like a pointer to the data that stayed the same so only the part that changes is “copied”.
- alentist 6y agoThere are smarter ways to deal with data structures in the functional setting than copying the entire structure over and over again. See https://en.wikipedia.org/wiki/Purely_functional_data_structure https://en.wikipedia.org/wiki/Purely_functional_data_structu... and Okasaki’s book Purely Functional Data Structures.
- heavyset_go 6y agoThere's Pyrsistent[1], which provides persistent data structures. [1] https://github.com/tobgu/pyrsistent https://github.com/tobgu/pyrsistent
- heavyset_go 6y agoYeah, Python would really benefit from multi-line anonymous functions. There was a limitation in Python where spacing and indentation gets ignored between parentheses, which makes it impossible to pass a multi-line lambda as an argument to a method or function. However, given the new parser, that limitation might be able to be mitigated.
- tutfbhuf 6y agoBut you can define functions inside of functions (recursively). def function1(): print ("hello outer") def function2(): print ("hello inner") function2() function1() Output: hello outer hello inner
- throwaway894345 6y agoBut you can’t do that (or try/except) in an expression such as a list comprehension or similar.
- robertlagrant 6y agoYes, because gross.
- deleted 6y ago[deleted]
- dragonwriter 6y agoNor, IMO, should you want to.
- throwaway894345 6y agoWhy not? Many other languages have closures and even Python has lambdas. Multi-line closures work well for these languages including in map/reduce/etc or comprehensions where applicable. Seems like your preference is overfit to Python’s limitations.
- cabalamat 6y agoGiven that Python allows unicode characters in source, I'm surprised it doesn't allow lambda to be replaced by the λ character.
- alrs 6y agoI'm surprised that you're surprised.
- JNRowe 6y agoFor those, like me, who get excited by this note that there are restrictions on the Unicode categories that are allowed, see the supported characters¹ and gory details². It is often enough to write math-y code in a usable way, but occasionally you'll find you can't use the character you want. ¹ https://docs.python.org/3/reference/lexical_analysis.html#identifiers https://docs.python.org/3/reference/lexical_analysis.html#id... ² https://www.python.org/dev/peps/pep-3131/ https://www.python.org/dev/peps/pep-3131/
- dragonwriter 6y agoThat would be quite unpythonic. Down that road lies Raku. EDIT: To be clear, I like Raku. But Python has its own distinct aesthetic.
- OJFord 6y agoWell you can't do `l = lambda` to replace it either, it's not really anything to do with allowing full unicode identifiers.
- vmchale 6y agoAlso the recursion limit.
- gameswithgo 6y agoI imagine it is problematic that Python is already very slow, and then to pile up idioms with performance downsides on top of that is kind of rough.
- jolux 6y agoFunctional programming doesn’t have an inherent performance downside, but it depends on specific optimizations in compilers and runtimes to make it fast. Python doesn’t really optimize anything from what I know.
- bj0 6y agoThis is one of the biggest reasons I really like (the python superset) Coconut: https://github.com/evhub/coconut https://github.com/evhub/coconut
- refactor_master 6y agoIt looks interesting, but I’m not entirely sold. All the examples are about math functions, which is kind of stupid to implement in Python. How does this benefit “plumbing”? My biggest problem with Python is that I either have to write list(function1(*function2(len(obj.method()))) Or try to avoid all the variables by using classes... which is fine... if it wasn’t for self taking up roughly a third of the word count.
- samasblack 6y agoI like the way the Functional Programming HOWTO in the Python docs (https://docs.python.org/3/howto/functional.html#small-functions-and-the-lambda-expression https://docs.python.org/3/howto/functional.html#small-functi...) puts it: Fredrik Lundh once suggested the following set of rules for refactoring uses of lambda: 1. Write a lambda function. 2. Write a comment explaining what the heck that lambda does. 3. Study the comment for a while, and think of a name that captures the essence of the comment. 4. Convert the lambda to a def statement, using that name. 5. Remove the comment.
- dragonwriter 6y agoFunctional programming in Python is severely hampered by the fact that Python is statement-oriented rather than expression-oriented. The lambda limitations are a product of this plus the particular whitespace rules Python has.
- patrec 6y agoThis has really not been true since python grew a ternary operator, syntactically you can write functional code perfectly fine in python -- the only significant syntactic shortcoming is lack of pattern matching. What actually hampers functional expression is semantics and mostly two-fold: 1. functions are terribly slow and always grow stack, so cannot replace iterative constructs. 2. Although python actually comes with a fair amount of functional data structures out of the box (str, bytes, tuple, frozenset, namedtuple, ...) none of them can be "updated" efficiently. There are some other things (exception as opposed to sum-type based error handling), but fixing the above would be enough to write functional code pretty unhampered, I think.
- dragonwriter 6y ago> Although python actually comes with a fair amount of functional data structures out of the box (str, bytes, tuple, frozenset, namedtuple, …) none of them can be “updated” efficiently. If they can’t be updated efficiently, they are just immutable than particularly functional.
- patrec 6y agoOf course I agree that calling such data structures immutable is more precise, but it's still in contrast to both imperative programming and imperative data structures. In particular every single functional language (including the purest of the pure) fairly heavily use immutable array based structures in one way or other. So if functional programming requires only using data structures with structural sharing, there are no functional programming languages.
- heavyset_go 6y ago
- raymondh 6y agoNot really. Python's lambda does pretty much what you would expect from Scheme. It creates a callable the binds arguments to parameters in a lexically scoped namespace and then evaluates the body of the lambda in that namespace. And with an open parenthesis, you can write multiline lambdas and indent it however you want. All the usual wizardry is possible: >>> ( lambda n: (lambda fact: fact(n, fact))( lambda n, inner: 1 if n == 0 else (n * inner(n - 1, inner)) ) )(5) 120 Also, Python has rough equivalents to some special forms in Scheme: (if testexp posexp negexp) ⟶ (posexp if testexp else negexp) (cond (p1 e1) (p2 e2) (else e3) ⟶ (e1 if p1 else e2 if p2 else e2) (begin e1 e2 e2) ⟶ [e1, e2, e3][-1] (and e1 e2 e3) ⟶ (e1 and e2 and e3) (or e1 e2 e2) ⟶ (e1 or e2 or e3) Some statements do have a functional form but aren't well known: class keyword ⟶ type(name, bases, namespace) import keyword ⟶ __import__(name, globals, locals, fromlist) You have map(), filter(), partial(), and reduce(). The operator module provides function equivalents for most operators. Also, the itertools were directly based on their equivalents in functional languages or array manipulation languages. That said, Python does lack some essential tooling that you would really miss: - There is no way to create new special forms. - Some important special forms are missing: let, let*, and letrec - The language spec precludes tail call optimization. - Some Python statements lack functional equivalents: try/except, with-statement, and assert-statement
- raymondh 6y agoActually there is a let and let* equivalent as well: (let* ((v1 e1) (v2 e2)) e3) ⟶ ((v1:=e1), (v2:=e2), e3)[-1] Dr. Racket example: > (let* ((x (+ 3 4)) (y (* x x))) (+ y (- x) 8)) 50 Python equivalent: >>> ((x:=3+4), (y:=x**2), y-x+8)[-1] 50
- Iwan-Zotow 6y agoYes, with walrus expression, lambda gains a lot of flexibility
- c-cube 6y agoExcept : - python scoping is not really lexical (and it captures variables, not the values they contain) - python is statement based, so lambdas are less powerful than in scheme. So not really the same thing.