6 ms·
everytime I see reduce(operator.add, ...) and variations like that I think GvR was right to relegate reduce to the functools module... it's just that
by _ZeD_ 13y ago
everytime I see
reduce(operator.add, ...)
and variations like that I think GvR was right to relegate reduce to the functools module... it's just that
sum(...)
covers the most common (90%? only?) usage...
- ak217 13y agoNot just that. More generally, comprehensions cover the most common use cases and are tremendously more readable.
- sirclueless 13y agoNot just the common ones, pretty much every one. Python 3 even removed the reduce builtin because it was so unreadable. Generator expressions and list comprehensions do so much more in a much more elegant way.
- jfarmer 13y agoHow can they do "so much more" when both map and filter can be implemented in terms of reduce, but the opposite is not true? I can agree with you in terms of readability, even as a mathematician. For example, the list comprehension syntax mirrors the mathematician's "set-builder notation," so it feels very natural. However, consider something like a "max", "min", or "argmax" function. Like map and reduce, you can implement this in terms of reduce, but I don't see how you can implement it in terms of a list comprehension. Or consider something like an RPN calculator, which could be implemented as a single reduce call whose initial value is an empty stack and whose input list is the list of RPN tokens. It seems that list comprehensions can do less in a very objective sense and couldn't be used to replace reduce without other supporting characters. Python has those supporting characters, of course, so there's a good 80/20 argument for favoring list comprehensions over a more opaque call to reduce.
- jfarmer 13y ago"Like map and filter," I mean, not "Like map and reduce."
- lost-theory 13y agoComprehensions can only be used to replace map & filter, not reduce.
- tome 13y agoComprehesions are more readable in the sense that they read more like "English" or "natural language". Unfortunately they're inherently non-composable and make refactoring harder. d0m's Moka example (https://news.ycombinator.com/item?id=6150944 https://news.ycombinator.com/item?id=6150944) is closer to composable. I would suggest the following modification. Instead of chaining methods, have a function "chain" which composes functions. We could then write chain(do(string.split, '+'), keep(lambda x: x != ""), map(int), reduce(moka.add)) If I decided that removing blanks and converting to int was a concept that was worth capturing in its own function, all that I need to do is splice out part of the chain as is. non_blanks_to_int = chain(keep(lambda x: x != ""), map(int)) chain(do(string.split, '+'), non_blanks_to_int, reduce(moka.add)) No modifications were required. It's more complicated with comprehensions. Of course it's still possible, but it's one more unneccessary grain of sand in the mechanism. Doing the same with the imperative version would be nigh-on impossible. Come to my FP days talk in Cambridge, UK, Thursday 24th October, 2013 if you want to hear more about this! http://lanyrd.com/2013/fpdays/sckzkz/ http://lanyrd.com/2013/fpdays/sckzkz/
- maxerickson 13y agoIf you take the awful step of naming things, comprehensions are easy enough to chain. That is (in untested python...) parts=s.split('+') keep=(s for s in parts if s) ints=(int(s) for s in keep) sum(ints) Hiding the middle steps there in a function is easy enough. That split returns a list, but the other steps are lazy.
- tome 13y agoBut naming your intermediate variables means it's not possible to splice parts out.
- maxerickson 13y agoYou did call it a grain of sand, but I suppose I'm responding to where you call it complicated. Moving a couple of the names into a separate function means passing in one of them and editing the last line (at least in python with explicit returns). That meets the meaning of more complicated, but (in my opinion) in a sort of hair splitting way.
- tel 13y agoGod no. If your loop isn't a map, it's almost certainly a fold. If you free up your syntax to make them easier to produce then they show up everywhere. Sum is a menial example.
- kazagistar 13y agoWhy not use a loop instead though?
- pestaa 13y agoBecause you need to track and update the temporary state. Maps and folds let you define your stepping algorithm separately.
- kazagistar 13y agoIn python? I wasn't aware that fold did anything other then iterate in order...
- calpaterson 13y ago> If your loop isn't a map, it's almost certainly a fold. ...all loops can be represented as folds
- tel 13y agoNot strictly true, but all maps can be represented as a fold. That's not usually the best tool though.
- tel 13y agoTo clarify this now that I'm not on my phone, folds may not express termination by themselves, they depend upon the type that they're folding up. More formally, folds are catamorphisms which operate on data, but you often need to use codata to generate the structures to fold over.
- tome 13y agoIf you define __add__ appropriately then it covers 100% of the use cases :)