19 ms·
I strongly think Python should have more functional programming support. Functional Programming Languages are usually scary to look at for many programmers. P
by frogcoder 5y ago
I strongly think Python should have more functional programming support. Functional Programming Languages are usually scary to look at for many programmers. Python would not only be a good FP introduction to them, it would also benefit greatly.
Years ago I found out the Guido wouldn't let tail recursion included, and even tried to remove map function from built in functions. Therefore I got the impression that python wouldn't have further support in FP. I really wish that is not the case. With the coming pattern matching in 3.10, My hope is high again.
I have very high respect for Guido van Rossum, I'm not here to discredit him. He's one of the authors in PEP 634.
I wish python would have simpler syntax for lambda which is currently using the lambda expression, even JS is doing better on this. A built-in syntax for partial would also be great. It could be even better if we can have function composition.
Some problems are better solved the FP way. It could even make the program more readable which is one of the strengths of Python.
- mjburgess 5y agoThey added "pattern matching" as a statement. The irrational hatred of FP is still there, to the point of the absurdity of implementing a hobbled procedural version of pattern matching! It is bordering on insane.
- toxik 5y agoPlease suggest a pattern matching expression syntax that doesn’t require completely changing how the language works. Pattern matching took so long because it was extremely hard to find that compromise, and I actually think they did an okay job. No, it won’t cover every case, but it will also cover the important ones.
- uryga 5y agox = match y: case 0: "zero" case 1: "one" case x: y = f(x) y+y print(x) it can require semicolons or parentheses or even braces somewhere if that's necessary to make the grammar work, idc. just don't make me type out `x = ...` a hundred times... (yes, i know you could use the walrus operator in the third case) (also, if anyone wants to reply with "use a named function because READABILITY", please save it)
- toxik 5y agoJudging by the votes you got, your proposal is not well-liked. In general, breaking Python's syntax rules to introduce block expressions or what you want to call it seems like a steep price to pay for what amounts to syntactic sugar in the end. However, your proposal actually misses the mark in the same way as the actual match/case does as well. What would be /really/ handy in Python is something like {'some_key': bind_value_to_this_name} = a_mapping because it is so common, especially if you're consuming a JSON API. You of course see the myriad problems with the above. I think you should read the PEPs on match/case, these things have actually been considered. One idea was to introduce a keyword to say which variables are inputs and which are outputs, but that also violates the general grammar in a way that isn't very nice. The accepted solution has warts, I agree, but at some point you just have to accept that you can't reach some perfect solution.
- uryga 5y ago> Judging by the votes you got, your proposal is not well-liked. i'm at peace with that :) [1] > In general, breaking Python's syntax rules to introduce block expressions or what you want to call it seems like a steep price to pay for what amounts to syntactic sugar in the end. that's your opinion, i disagree! i think Python would be a better, more pleasant to use language if they figured this out. a girl can dream, ok? > What would be /really/ handy in Python is something like {'some_key': bind_value_to_this_name} = a_mapping yes, extending the destructuring syntax would be nice, i agree! but the original question was "Please suggest a pattern matching expression syntax [...]", and the post you were responding to was specifically talking about `match`'s syntax. [2] > I think you should read the PEPs on match/case i read them when they came out. i'm assuming you're referring to this section from PEP 622: > "In most other languages pattern matching is represented by an expression, not statement. But making it an expression would be inconsistent with other syntactic choices in Python." https://www.python.org/dev/peps/pep-0622/#id77 https://www.python.org/dev/peps/pep-0622/#id77 i believe Python's statement-orientatation kinda sucks, so to me this is just "things aren't great, let's stay consistent with that". yeah, yeah, "use a different language if you don't like it" etc. --- [1] well, maybe not quite, after all i'm here arguing about it. [2] `match` uses patterns like the one you described in `case` arms, but is distinct from them. i don't see why dict-destructuring syntax couldn't be added in a separate PEP.
- clavigne 5y agoHere is pattern matching as a library that is not built using statements, https://github.com/santinic/pampy https://github.com/santinic/pampy Clearly it's possible. It's also more ergonomic than PEP 622.
- toxik 5y agoInteresting idea, though falls short of FP matching again. The syntax we actually have does a lot more.
- matsemann 5y agoYes, coming back to Python after many years with Kotlin and Elm, I see how the Python language guides people to write code in a more unreadable way. Mutations everywhere. But mainly because mapping and flatting stuff is so burdensome. And it lacking many fp functions and a proper way to call them ergonomically makes a crazy list comprehension the goto tool, which often is much less explicit about what's going on than calling a function with a named and widely understood concept.
- zbentley 5y ago> And it lacking many fp functions and a proper way to call them ergonomically makes a crazy list comprehension the goto tool, which often is much less explicit about what's going on than calling a function with a named and widely understood concept. I've said roughly this before somewhere on HN but cannot find it right now: list comprehensions are like regexes. Below a certain point in complexity, they're a much cleaner and immediately-graspable way of expressing what's going on in a given piece of code. Past that point, they rapidly become far worse than the alternative. For example, "{func(y): y for x, y in somedict.items() if filterfunc(x)}" is clearer than the equivalent loop-with-tempvars, and significantly clearer than "dict(map(lambda k: (func(somedict[k]), somedict[k]), filter(filterfunc, somedict.keys()))))". Even with some better mapping utilities (something like "mapkeys" or "filtervalues", or a mapping utility for dictionaries that inferred keys-vs-values based on the arity of map functions), I think the "more functional" version remains the least easily intelligible. However, once you cross into nested or simultaneous comprehensions, you really need to stop, drop, and bust out some loops, named functions, and maybe a comment or two. So too with regex! Think about the regex "^prefix[.](\S+) [1-7]suffix$"; writing the equivalent stack of splits and conditionals would be more confusing and easier to screw up than using the regex; below a point of complexity it's a much clearer and better tool to slice up strings. Past a point regexes, too, break down (for me that point is roughly "the regex doesn't fit on a line" or "it has lookaround expressions", but others may have different standards here).
- XorNot 5y agoThe annoying thing is they have a performance cost though: list comprehensions can be very fast because they stay in the C codepath of Python, whereas unrolled into a loop you lose some of that.
- jazzyjackson 5y agoLearn You a Haskell for Great Good taught me list comprehension, and I was surprised to see such a pithy shorthand available in Python (+ dict comprehension). That's a very functional way to transform objects from one shape to another with an in-line expression, no lambda keyword there. But even the lambda keyword isn't so bad, you can create a dictionary of expressions to call by name, a lot more compact them declaring them the usual way imo: https://github.com/jazzyjackson/py-validate/blob/master/pyvalidate.py#L22 https://github.com/jazzyjackson/py-validate/blob/master/pyva... To your point, I only recently learned there's a Map function in Python, while in JS I'm .map(x=>y).filter(x=>y).reduce(x=>y)ing left and right.
- frogcoder 5y agoYes! List/Dictionary/Generator comprehension is one big plus for Python, it probably came from the functional world. I use it whenever I can. > But even the lambda keyword isn't so bad, you can create a dictionary of expressions to call by name, a lot more compact them declaring them the usual way imo: https://github.com/jazzyjackson/py-validate/blob/master/pyva https://github.com/jazzyjackson/py-validate/blob/master/pyva... lambda keyword is better than nothing, it definitely can be improved. Just imaging using javascript syntax in your example. > To your point, I only recently learned there's a Map function in Python, while in JS I'm .map(x=>y).filter(x=>y).reduce(x=>y)ing left and right. I think with the introduction of list comprehension Guido saw map function was no longer needed, that was why he wanted it removed. I don't deny it, but using map and filter sometimes are just easier to read. Say [foo(v) for v in a] vs map(foo, a).
- 0x008 5y agoYes but map in Python is riduclously slow when map is combined with a lambda [1] [1]: https://stackoverflow.com/questions/1247486/list-comprehension-vs-map https://stackoverflow.com/questions/1247486/list-comprehensi...
- kzrdude 5y agoIt's a bit hard to find recent numbers in that decade-old thread, but the relevant, more up to date, evidence I see (in this answer) says that map is not much slower than a list comprehension: https://stackoverflow.com/a/57104206 https://stackoverflow.com/a/57104206
- architech 5y ago> It could be even better if we can have function composition. I think composition and piping are such basic programming tools that make a lot of code much cleaner. It's a shame they're not built-in in Python. So, shameless plug, in the spirit of functools and itertools I made the pipetools library [0]. On top of forward-composition and piping it also enables more concise lambda expressions (e.g. X + 1) and more powerful partial application. [0] https://0101.github.io/pipetools/doc/ https://0101.github.io/pipetools/doc/
- patterns 5y agoI agree. One gripe that I have with functions like map is that it returns a generator, so you have to be careful when reusing results. I fell into this trap a few times. I'd also like a simpler syntax for closures, it would make writing embedded DSLs less cumbersome.
- zbentley 5y ago> One gripe that I have with functions like map is that it returns a generator, so you have to be careful when reusing results I hope that is never changed; I often write code in which the map function's results are very large, and keeping those around by default would cause serious memory consumption even when I am mapping over a sequence (rather than another generator). Instead, I'd advocate the opposite extreme: Python makes it a little too easy to make sequences/vectors (with comprehensions); I wish generators were the default in more cases, and that it was harder to accidentally reify things into a list/tuple/whatever. I think that if the only comprehension syntax available was the one that created a generator--"(_ for _ in _)"--and you always had to explicitly reify it by calling list(genexp) or tuple(genexp) if you wanted a sequence, then the conventions in the Python ecosystem would be much more laziness-oriented and more predictable memory-consumption wise. Ah well, water under the bridge, I know.
- EE84M3i 5y agoPersonally, I mostly just avoid using map/filter and use a list/generator/set/dict comprehension as required. I don't find map(foo, bar) much easier to read than [foo(thingamajig) for thingamajig in bar]
- robertlagrant 5y agoYes, this is I think why Guido wanted to get rid of map() syntax - he prefers comprehension syntax.
- ehsankia 5y agoSimply wrap it in list(), or use a list comprehension. Most things in python3 are iterators now, so the same thing applies to many things.
- ehsankia 5y agoAren't you contradicting yourself a bit? First you claim functional languages are scary to look at, then say that you want Python to become more like functional languages. But maybe the reason Python is elegant and easier to read is exactly because Guido had the self-constraint to not go full functional. You also miss the part of the story where he actually did remove `reduce` from builtin, exactly because of how unreadable and confusing it is to most. It's exactly that kind of decision making I expected from a BDFL, and I think Guido did a great job while he was one keeping Python from going down such paths.
- collyw 5y agoI was going to say something to that effect. Functional programming is kind of cool unless it's someone else's code and you need to debug it.
- ebingdom 5y agoI'd much rather debug someone's pure functional code rather than trying to figure out how someone's imperative code got into some unexpected/invalid state.
- frogcoder 5y agoWell, the BDFL is probably the only dictator we all love. Any decision he made is infinitely more than I could. Because I am just a python user, and an outsider in any decision making process. So for me, he's right all the time. That's a perfect definition of a dictator :) But I do have wishes. It's like I love my parents but I do want to stay up late sometimes. Yeah, I totally missed the part he removed reduce from builtin. Sorry about my memory. map, filter, or reduce, it does not matter. As I stated, some problems are better solved functional way. Because Python is such a friendly language, if it includes functional paradigm properly, it would make the functional part more readable than other functional languages. FP is scary not because it has evil syntax to keep people at distance, it's just an alien paradigm to many. Lot's of non functional languages has functional support, which doesn't make them less readable. E.g. C#, JS. I suspect these languages have helped many understanding FP more. Python could make the jump by including more FP, but not turning into a full-fledged FP. BTW. I'm still glad reduce is kept in functools.