6 ms·
In python, you could type it fairly loosely. Which is more readable, and also helps you catch errors. There's not so much coupling. from typing import Call
by renesd 10y ago
In python, you could type it fairly loosely. Which is more readable, and also helps you catch errors. There's not so much coupling.
from typing import Callable, Iterable
def filter(pred: Callable, xs: Iterable) -> Iterable:
return [x for x in xs if pred(x)]
filter(lambda x: x>1, [1,2,3])
If you tighten it up to only take iterables of ints.
from typing import Callable, Iterable
def filter(pred: Callable, xs: Iterable[int]) -> Iterable:
return [x for x in xs if pred(x)]
filter(lambda x: x>1, [1,2,3])
filter(lambda x: x>1, [[1],[2],[3]]) # this is an error
Float is duck type compatible with int. So if you specify float, it accepts ints and floats. If you specify int, it only accepts ints.
from typing import Callable, Iterable
def filter(pred: Callable, xs: Iterable[float]) -> Iterable:
return [x for x in xs if pred(x)]
filter(lambda x: x>1, [1,2,3])
filter(lambda x: x>1, [1.01, 2.09, 3.34])
The moral of the story is to be as accepting as you can be unless there is an actual need to be very picky about what you accept. (Perhaps if you're doing integer arithmetic, and your code only works with ints, then require ints).
- lngnmn 10y agoThe very beauty and reason behind filter is in that it does not care about its arguments. It is a logical construct - if predicate is satisfied - keep it. The ADTs, type-tagging, predicate logic and duck-typing are superior and less cluttered than homogeneous box-like variables and restricted homogeneous conditionals are - the cost of static typing. Yes, one could shot himself in the foot, but one also could run instead of crawl.
- renesd 10y agoQuack, quack. I'm a duck.
- mannykannot 10y agoSometimes it is more important to not shoot oneself in the foot than it is to run. These discussions always end up with two antagonistic camps, so let's acknowledge that we can choose the degree of language support, in keeping a program's semantics as intended, according to the circumstances. Language selection is an aspect of engineering judgement.
- lngnmn 10y agoBut I nevertheless would argue that this (item for item in iterable if predicate(item)) is vastly superior idiom and the principles behind dynamically-typed languages, which makes this idiom possible, are sound. filter(P, []) -> []; filter(P, [H|T]) -> filter(P(H), H, P, T). filter(true, H, P, T) -> [H|filter(P, T)]; filter(false, H, P, T) -> filter(P, T). Look, ma, no IFs
- coldtea 10y ago>is vastly superior idiom What makes it superior? Just that is appears more generic? It actually isn't. As long as it's passed an object for iterable that's not iterable it will break. At runtime. As long as it's passed an item inside an iterable that's not compatible with the testing predicate makes, it will fail. At run time. The only reason it looks more generic is that it does LESS.
- lngnmn 10y agoIt not "appears", it is generic. As generic as it could be. This particular line is also a generator comprehension which produces a lazy sequence. Run-time errors and so-called null-propagation are well-known issues and once code passed unit tests it is no less trustworthy in principle than statically-typed one. In the first run, yes, there is a chance of a run-time error. The dynamic languages, notably Lisps, Erlang, Python and Ruby are proved to be superior for quick prototyping and so-called exploratory programming, which has been popularized by pg, along with bottom-up design and the layered-DSLs architecture, in the OnLisp book. Another classic example is Norvig's Design Patterns in Dynamic Languages which basically ridiculed the whole thing. There are distinct cultures around MIT Scheme and Common Lisp, Smalltalk and now Python which emphasize expressiveness, minimalism and readability. Such an erudite like you should know this.
- coldtea 10y ago>It not "appears", it is generic. As generic as it could be Only in the sense that accepting arguments that it shouldn't accept and it'll crash with, is part of the general description of the filtering operation -- which is not. If you prefer, it's "more generic" than it should be. It's not a generic description of the "filter" operation, but a generic description of the "process_input_and_produce_output" operation. >The dynamic languages, notably Lisps, Erlang, Python and Ruby are proved to be superior for quick prototyping and so-called exploratory programming Where is that proof published? And what methodology did it follow? Since, you know, we are computer SCIENTISTS and all...