5 ms·
Sadly, Python is a pretty poor functional language. The core of functional programming is about avoiding mutable states, not much about anonymous functions or
by raphaelj 3y ago
Sadly, Python is a pretty poor functional language.
The core of functional programming is about avoiding mutable states, not much about anonymous functions or passing functions as data.
To do proper functional programming in Python, there should be IMO:
- a way to enforce non-mutable variables/objects;
- non-mutable collections;
- proper support for recursion and tail-recursion optimization;
- a better syntax for anonymous functions than single statement lambdas.
Generators are nice, but do not have much to do with functional programming.
- qbasic_forever 3y agoI agree but it's not so dire, the tuple type (and variants like namedtuple) is pretty powerful, non-mutable and often my first choice for data structure in python. Everything else can be built on top of it if you're really motivated.
- amanj41 3y agoI would add frozenset as the other immutable collection. The other points are well taken though
- linkdd 3y agoFor tail recursion, you can use this snippet of code: class Recurse(Exception): def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs class Terminate(Exception): def __init__(self, retval): self.retval = retval def tailrec(func): def wrapper(*args, **kwargs): while True: try: func(*args, **kwargs) except Recurse as r: args = r.args kwargs = r.kwargs except Terminate as t: return t.retval return wrapper @tailrec def fact(n, acc=1): if n == 0: raise Terminate(acc) else: raise Recurse(n - 1, acc * n) Of course, it will be slow because it relies on exceptions :P
- _aavaa_ 3y agoYou can do a similar thing (that's around 2-3x faster) with a trampoline: def factorial(n): res = fac(n) while callable(res): res = res() return res def fac(n, acc=1): if n == 1: return acc else: return lambda: fac(n-1, n*acc)
- deleted 3y ago[deleted]
- odyssey7 3y agoAgreed, Python is designed for something other than functional programming, so a functional programming enthusiast would get better mileage out of something else. Even if you were to write all of your Python programs against the grain in a functional style, you'd still need to operate in a community of modules that don't provide referential transparency.
- theLiminator 3y agoEven worse when some modules have global mutable state like matplotlib and co.
- tayo42 3y agoWhy do you consider anonymous functions so important? Regular functions can be used the same way?
- sodapopcan 3y agoOP said anonymous functions are NOT as important as immutable data.
- tayo42 3y agoits in the list they provided of improvements python needs...
- profunctor 3y agoIt's not a list of improvements python needs. It's a list of things python already does / has.
- tayo42 3y agodo I have bots responding to me? whats hard about comprehending this? > To do proper functional programming in Python, there should be IMO: > ... > - a better syntax for anonymous functions than single statement lambdas.
- deleted 3y ago[deleted]
- sodapopcan 3y agoOh... either that was added in an edit or I had a brain blip that caused me to skip the bulleted list. Apologies.
- gnufx 3y agoYou want tail call optimization, not just tail-recursion, i.e. mutually recursive functions.
- carapace 3y agoSyntactically maybe, but I find it has a quite workable functional subset. Integers, floats, tuples, named tuples, and frozensets are all immutable, functions are values, etc. E.g.: https://joypy.osdn.io/notebooks/Derivatives_of_Regular_Expressions.html https://joypy.osdn.io/notebooks/Derivatives_of_Regular_Expre... -or- https://github.com/calroc/xerblin/blob/master/xerblin/btree.py https://github.com/calroc/xerblin/blob/master/xerblin/btree.... It's not fantastic, but it's not that bad.
- gnulinux 3y agoI love both python and functional programming and I do write functional style python routinely. One barrier I hit is there is no immutable dict type. There is MappingProxyType but it's insufficient. I prefer using custom dataclass like objects built with pydantic and type checked with mypy. It's better than dict and can be made immutable but requires tons of boilerplate code which is a bit unpythonic.
- carapace 3y ago> there is no immutable dict type Does the namedtuple not suffice? Apologies if I'm being dense. - - - - It's not an immutable dict type (for one thing, this has linear lookup, the BTree would be better) but it's fun: https://stackoverflow.com/questions/13708701/how-to-implement-a-dictionary-as-a-function-in-ocaml https://stackoverflow.com/questions/13708701/how-to-implemen... In Python: from functools import partial def empty_dict(key): raise KeyError def _dict_add(dictionary, key, value, lookup): return value if key == lookup else dictionary(lookup) def dict_add(d, key, value): return partial(_dict_add, d, key, value) d = empty_dict d = dict_add(d, 'key0', 23) d = dict_add(d, 'key1', 18) And then... >>> d('key0') 23 >>> d('key1') 18 >>> d('keyn') Traceback (most recent call last): File "<pyshell#8>", line 1, in <module> d('keyn') File "/usr/home/sforman/tmp_fn_dict.py", line 7, in _dict_add return value if key == lookup else dictionary(lookup) File "/usr/home/sforman/tmp_fn_dict.py", line 7, in _dict_add return value if key == lookup else dictionary(lookup) File "/usr/home/sforman/tmp_fn_dict.py", line 4, in empty_dict raise KeyError KeyError - - - - > objects built with pydantic and type checked with mypy FWIW, after ~15 years of professional Python development, I'm not into types [in Python]. My attitude is that if you really need them you should switch to e.g. OCaml or something that does them right. I love Python but I wouldn't use it anymore for anything other than scripts and maybe prototyping.
- pjmlp 3y agoNot for Lisp or some ML derived languages, FP isn't whatever Haskell does.
- archarios 3y agoNot having immutability isn't the worst thing IMO. I guess if you can't trust your coworkers to not modify their inputs, it's a different story.
- harry8 3y ago> The core of functional programming is about avoiding mutable states, I can't keep up, does this mean scheme is not a functional language anymore by modern definition?
- znafelrif 3y ago> The core of functional programming is about avoiding mutable states, not much about anonymous functions or passing functions as data. I disagree since any paradigm can be done either with or without mutable state. So it is not something that defines functional programming. In any case you can also use immutable data types with python anyway. The main annoyance with python is in my opinion your last point: The lambda syntax is too limited. So it is necessary to define lots of nested small functions instead. Also python syntax is not as nice in chaining function calls over multiple lines.
- elesiuta 3y ago> Also python syntax is not as nice in chaining function calls over multiple lines. Not sure if this is exactly what you meant, but I implemented something like this in reply to a similar comment a few months ago which may be of interest. https://news.ycombinator.com/item?id=35105298 https://news.ycombinator.com/item?id=35105298
- tpoacher 3y agoI use this approach [0]. Works well enough for me and is visually adequate for "piping"-style code. 0. https://sr.ht/~tpapastylianou/chain-ops-python/ https://sr.ht/~tpapastylianou/chain-ops-python/
- chlorion 3y agoI do not think functional programming is about mutable state at all. It's about functions being first class values, nothing more. Lisp and Scheme are examples of functional languages that do not restrict mutability. The term for what you are talking about is pure functional programming!
- kazinator 3y agoI don't think this is correct. Programming languages with support for functional programming are not always pure functional languages. However, functional programming per se is always pure by definition; if you're mutating anything, it's not functional. (You can have "quasi functional" if you mutate only local variables, such that the black box view of your functions appears pure. Nobody knows whether the map function in (map f list) internally contains a loop or tail recursion.) Languages which support functional programming and other paradigms are not called functional; it is not correct to call Common Lisp and Scheme functional. Not only do these have mutation, they have sequencing via strict evaluation: doing one thing that has a side effect, followed by another. Side effects like I/O and mutation are easily obtained and ordered, just like in Fortran or Java.
- chlorion 3y agoPure functional programming is always about purity, functional programming is about first class functions. Pure functional programming is a subset of functional programming, not the other way around. I'm not really sure where you are getting your information from but everything that I have read disagrees with this idea that functional programming is about purity. https://en.wikipedia.org/wiki/Functional_programming https://en.wikipedia.org/wiki/Functional_programming I think in recent times the term functional programming has been overloaded to mean what you describe, and many people use it that way, but I don't think it should be used that way. Maybe we should just say "non pure functional" or "pure functional" so it's always clear what we are talking about!
- deleted 3y ago[deleted]