3 ms·
Python syntax is very very well suited for functional programming. A python map and filter is done with list comprehensions and even flatmap is doable within th
by deltaonefour 5y ago
Python syntax is very very well suited for functional programming. A python map and filter is done with list comprehensions and even flatmap is doable within the list comprehension ecosystem. Additionally the syntax transfers over to inputting values into n-arity functions and even dictionary comprehensions. Note that this feature Isn't even part of the python standard library... map and filter and flatmap are an inherit part of the CORE syntax. It makes it much better suited for FP then javascript imo.
x = [i*2 for i in range(5)] #[0, 2, 4, 6, 8]
y = [i for i in range(8) if i%2 == 0] #[0, 2, 4, 6, 8]
z = [[1],[2],[3],[4]]
w = [j for i in z for j in i] #[1,2,3,4]
t = {str(j):j*2 for j in w} #{"1":1, "2":4, "3":6, "4":8}
#reduce (note the generator (i for i in range(20))... that's a lazy list essentially)
reduce(lambda acc, x: x + acc, (i for i in range(20)), 0) #sum(0 ... 20)
#get max value from a bunch of numbers:
f = max(i for i in range(30) if 30 % 3 == 0) #max(0, 3, 9, 12, 15, 18, 21, 24, 27, 30) = 30
#basic recursion
def myreverse(x: str) -> str:
return x if len(x) <= 1 else x[-1] + myreverse(x[:-1]) #O(N) on each slice, (However x[-1] is O(1) unlike the haskell list).
#qsort haskell style
def qsort(l: List[int]) -> List[int]:
return l if len(l) <= 1 else qsort([i for i in l if i <= l[0]]) + qsort([i for i in l if i > l[0]])
Python also supports pattern matching shown here: https://www.python.org/dev/peps/pep-0636/ https://www.python.org/dev/peps/pep-0636/
Additionally lambda syntax, aka python anonymous first class functions HAVE to be functional.
f = lambda x: x + 1
There is no procedural concepts like variable assignment allowed in a python lambda. This is done because they wanted to force the python lambda to be properly functional and short.
The type hints that python uses are also quite good with support for generics sum types and even type level programming (however your type checker needs to support it too and basically none of them do right now) You can literally assign a type to a variable in python. See: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
I would say the main weakness in python is that the IMPLEMENTATION is not well suited for functional programming (but the syntax VERY much is). Tail slices on lists like x[1:] cost O(N) and that's the biggest issue right now imo. It makes some valid solutions on leetcode exceed the time limit because it adds and additional N complexity on every slice when the head and tail functions in haskell cost O(1)
I'm sure some library can easily provide the underlying functional primitives python needs to be faster. Actually on that note, does anyone know of a library that solves the head tail slicing problem I described above? Probably should use the python deque, but the api for that is inherently not functional.
- keithasaurus 5y ago> There is no procedural concepts like variable assignment allowed in a python lambda. Just a small note that the walrus operator gives you some wiggle room here: add_5_to_square_if_greater_than_10 = lambda x: squared + 5 if (squared := x * x) > 10 else x assert add_5_to_square_if_greater_than_10(2) == 2 assert add_5_to_square_if_greater_than_10(5) == 30
- deltaonefour 5y agoyeah my bad. Not fully up to date with all the newer python 3 tricks. That walrus operator is a trap though imo.
- dragonwriter 5y ago> Additionally lambda syntax, aka python anonymous first class functions HAVE to be functional. They have to be a single python expression, but that’s not the same as the usual understanding of “functional” (i.e., referentially transparent). Consider: d = {"foo": 1} f = lambda m: d.update({k, v+d.get(k,0) for k,v in m.items()}) or d > Tail slices on lists like x[1:] cost O(N) and that's the biggest issue right now imo. It makes some valid solutions on leetcode exceed the time limit because it adds and additional N complexity on every slice when the head and tail functions in haskell cost O(1) Python lists are not lisp-style lists, which is more efficient for most uses, but not for a lot of functional-style algorithms which leverage cheap head/tail splits. But it wouldn't be hard to write a typed sequence class that wrapped a lisp-style immutable list implemented with nested tuples with the deepest nested one an empty tuple in Python, there's just not a lot of demand for it.
- deltaonefour 5y ago>They have to be a single python expression, but that’s not the same as the usual understanding of “functional” (i.e., referentially transparent). Consider: True, yeah >But it wouldn't be hard to write a typed sequence class that wrapped a lisp-style immutable list implemented with nested tuples with the deepest nested one an empty tuple in Python, there's just not a lot of demand for it. A doubly linked list with the same slice syntax would be fine. You can use java style classes as it's just the underlying implementation. There's no demand (currently) but it's a good idea as python syntax works extremely well (better then even javascript) for functional programming.