7 ms·
I think it does, actually. Python also has many of Haskell's features (list comprehensions, map/filter/reduce, itertools, functools, etc.). But I only started r
by setopt 2y ago
I think it does, actually. Python also has many of Haskell's features (list comprehensions, map/filter/reduce, itertools, functools, etc.). But I only started reaching for those features after learning about them in Haskell.
In Python, it's very easy to just write out a for-loops to do these things, and you don't necessarily go looking for alternative ways to do these things unless you know the functional equivalents already. But in Haskell you're forced to do things this way since there is no for-loop available. But after learning that way of thinking, the result is then more compact code with arguably less risk of bugs.
- z500 2y agoIf anything, Python encourages you to use loops because the backwards arrangement of the arguments to map and filter makes it painful to chain them.
- sgarland 2y agomap(function, iterable) That seems very logical to me, but then, I’m not a functional programmer, I just like map. It’s elegant, compact, and isn’t hard to understand. Not that list comps are hard to understand either, but they can sometimes get overly verbose. filter has also lost ground in favor of list comps, partially because Guido hates FP [0], and probably due to that, there has been a lot of effort towards optimizing list comps over the years, and they’re now generally faster than filter (or map, sometimes). [0]: https://www.artima.com/weblogs/viewpost.jsp?thread=98196 https://www.artima.com/weblogs/viewpost.jsp?thread=98196
- BeetleB 2y agoYes, but how do you chain them? map(func4, map(func3, map(func2, map(func1, iter)))) vs iter.map(f1).map(f2).map(f3).map(f4) I made up the syntax for the last one, but most functional languages have a nice syntax for it. Here's F#: iter |> f1 |> f2 |> f3 |> f4 Or plain shell: command | f1 | f2 | f3 | f4
- TylerE 2y agoYou don't. Use generator syntax, which is really the more pythonic way to it. >>> iter = [1,2,3,4] >>> f1 = lambda x: x*2 >>> f2 = lambda x: x+4 >>> f3 = lambda x: x*1.25 >>> [f3(f2(f1(x))) for x in iter] [7.5, 10.0, 12.5, 15.0]
- BeetleB 2y agoFirst off, writing f3(f2(f1(x))) is painful - keeping track of parentheses. If you want to insert a function in the middle of the chain you have some bookkeeping to do. Second, that's all good and well if all you want to do is map. But what if you need combinations of map and filter as well? You're suddenly dealing with nested comprehensions, which few people like. In F#, it'll still be: iter |> f1 |> f2 |> f3 |> f4 Here's an example from real code I wrote: graph |> Map.filter isSubSetFunc |> Map.filter doesNotContainFunc |> Map.values |> Set.ofSeq This would not be fun to write in List Comprehensions, but you could manage (only two list comprehensions). Now here's other code: graph |> removeTerminalExerciseNodes |> Map.filter isEmpty |> Map.keys |> Seq.map LookUpFunc |> Seq.map RemoveTrivialNodes |> Seq.sortBy GetLength |> Seq.rev |> Seq.toList BTW, some of the named functions above are defined with their own chain of maps and filters.
- Izkata 2y agoAn alternative for python is to flip what you're iterating over at the outermost level. It's certainly not as clean as F# but neither is it as bad as the original example if there's a lot of functions: iter = [1,2,3,4] f1 = lambda x: x*2 f2 = lambda x: x+4 f3 = lambda x: x*1.25 result = iter for f in [f1, f2, f3]: result = [f(v) for v in result] Then the list comprehension can be moved up to mimic more closely what you're doing with F#, allowing for operations other than "map": result = iter for f in [ lambda a: [f1(v) for v in a], lambda a: [f2(v) for v in a], lambda a: [f3(v) for v in a], ]: result = f(result) And a step further if you don't like the "result" reassignment: from functools import reduce result = reduce(lambda step, f: f(step), [ lambda a: [f1(v) for v in a], lambda a: [f2(v) for v in a], lambda a: [f3(v) for v in a], ], iter)
- itishappy 2y agoDon't Haskell and Python use the same argument order? filter(lambda x: x<5, map(lambda x: 2*x, [1,2,3,4,5])) filter (<5) . map (*2) $ [1,2,3,4,5] (Technically the Python version should be cast to a list to have identical behavior.) Same with comprehensions (although nesting comprehensions will always get weird). [x for x in [2*x for x in [1,2,3,4,5]] if x<5] [x | x <- [2*x | x <- [1,2,3,4,5]], x<5]
- justincredible 2y ago[dead]