10 ms·
halve_evens_only = lambda nums: map(lambda i: i/2, filter(lambda i: not i%2, nums)) I still find it rather silly that python doesn't supper a nice list map/fil
by lihaoyi 14y ago
halve_evens_only = lambda nums: map(lambda i: i/2, filter(lambda i: not i%2, nums))
I still find it rather silly that python doesn't supper a nice list map/filter; it could be so much nicer
nums.filter(lambda i: i%2 == 0).map(lambda i: i/2)
If they did, even including the annoyingly long-to-type "lambda". List comprehensions are cool and all, but do not really scale visually (i.e. get rather messy) when you have more than one map and filter step.
These arbitrary break-away from OO method style into module+data style (len(L) is another!) are one of the things I hate most about Python. There are some reasons for doing so, but a pure-OO (like Scala) or pure-method+data (like F#) would have saved me many a runtime error.
- darkstalker 14y agothe D language supports that kind of syntax nums.filter!(i => i%2 == 0).map!(i => i/2);
- fferen 14y agoTo elaborate, this is because of D's Uniform Function Call Syntax (http://www.drdobbs.com/blogs/cpp/232700394 http://www.drdobbs.com/blogs/cpp/232700394) - any function that takes an object as first argument can be called as though it were a method of that object; "map" and "filter" are actually functions in the std.algorithm module. It's a pretty neat trick and although in principle it could make things harder to reason about I haven't had any problems with it so far.
- lihaoyi 14y agoso does Scala stuff.filter(_ % 2 == 0).map(_ / 2) and C#, demonstrating that this isn't some obscure feature that only language geeks care about: Stuff.Where(x => x % 2 == 0).Select(x => x / 2) My point isn't that this sort of syntax is new and novel, it's just that in Python it's annoyingly inconsistent. There are reasons where you would want to use type-class style modules to structure your code in a certain way, but I do not think python's map() filter() reduce() and len() qualify as these cases
- swdunlop 14y agoPython offers filtering expressions in its generator syntax. I find Python's "lambda" hurts readability for most uses, which pains me as a Lisp geek. Your example, as a generator: halve_evens_only = (i / 2) for i in nums if (i%2 == 0) The parens aren't necessary, but they help readability for people who aren't used to the generator order of operations. (Again, Lisp geek, more parens means more readable in my fractured mind.)
- dmg8 14y agoThe parens are required. What you've written raises a SyntaxError. You can omit them in the generator expression if it's being passed directly as the only parameter to a function: halve_evens_only = list(i/2 for i in nums if i % 2 != 0)
- deleted 14y ago[deleted]
- Peaker 14y agohalve_evens_only = map (/2) . filter even
- euccastro 14y agoI think only familiarity with Javascript makes that "nice". One could argue that this (lambda i: i%2 == 0).filter((lambda i: i/2).map(nums)) makes (marginally) more sense. But I like filter and lambda alright as they are. I agree Python's inconsistency in this is a bit unfortunate, but I haven't had much of a problem with the runtime errors you mention.
- pcwalton 14y agoRust typeclasses solve this problem; you can create a suite of methods with syntax like this: impl methods<T> for [T] { fn filter(f : fn(T)->bool) -> [T] { ... } fn map<U>(f : fn(T)->U) -> [U] { ... } } And then you can call it with syntax like: println(#fmt("%?", [ 1, 2, 3 ].map { |x| x + 3 })); // prints "[ 4, 5, 6 ]" The methods are properly scoped, so code that isn't in your module needs to import your methods to use them. That way, you avoid introducing strange action-at-a-distance in your code.