Closed olegnn closed 3 years ago
That seems like a spotfix for just one function that takes predicates, a more general solution would be adding a trait for predicate functions that provides .negate()
on function pointers.
Prior art: the java standard library function interface for predicates
In my opinion, .negate()
function will only make code less readable because to apply it in place we should write
let odds = iter.filter((|&a| a % 2 == 0).negate()) // which is much less readable than
let odds = iter.filter(|&a| a % 2 != 0) // and
let odds = iter.filter(|&a| !(a % 2 == 0))
If apply to defined function, it still will lose to |v| !f(v)
let odds = iter.filter(is_even.negate());
let odds = iter.filter(|v| !is_even(v));
I didn't write any code on Java for many many years and I don't know anything about its current status, but as far as I know most of modern JVM-compatible languages have the same reject
function:
Kotlin filterNot Scala filterNot Clojure remove
Iterator trait contains 11 functions which take predicate - all
, any
, filter
, skip_while
, take_while
, partition_in_place
, partition
, is_partitioned
, find
, position
, rposition
.
I think it's obvious why any
, find
, partition_in_place
, partition
, is_partitioned
,position
, rposition
, skip_while
/ take_while
don't suggest to have opposite versions.
So we have two functions all
and filter
. all
may have opposite function none
which checks that no elements match given predicate and filter
may have reject
function as described above.
In many languages it's called filterNot
but I'd prefer reject
because filter_not
looks a bit bulky.
reject
seems to be the result of languages convenience evolution - for example, in Erlang there's no such function but its modern version Elixir has it https://hexdocs.pm/elixir/Stream.html#reject/2.
I think it's obvious why any, find [... ]don't suggest to have opposite versions.
While all
could be negated by a universal quanitification none
there could also be a negated existential quantification as the opposite for any, it would check that there exists at least one element where the predicate doesn't hold true.
Similarly one could find the first element that does not match a predicate, if any.
At least logically those are valid constructs, perhaps they don't have many uses in practice, the point is that the concern of negation is one of the predicate, not of the iterator.
If apply to defined function, it still will lose to |v| !f(v)
let odds = iter.filter(is_even.negate()); let odds = iter.filter(|v| !is_even(v));
Well, perhaps it could be implemented as std::ops::Not
? Then you could either
.filter(is_even.not())
.filter(not(is_even))
.filter(!is_even)
This could be further extended to other boolean operators, then has the option to either use operators or function calls in prefix or infix position to combine predicates.
.filter(divisible_by_three.or(divisible_by_five))
.filter(or(divisible_by_three, divisible_by_five))
.filter(divisible_by_three || divisible_by_five)
I think this also has the advantage that these types can be named and could be specialized on.
If anyone wants this, I suggest they just make a PR. This is a small thing that just needs some libs teams eyes on it to see what they think. (I'm personally not a fan of this, and would rather invert whatever's in the closure, but it's not up to me.)
Going to close this. If a PR is opened then that can be used for tracking.
I opened a PR for this: https://github.com/rust-lang/rust/pull/93708
This method will act as a
filter
with a complement of the provided predicate.If function defined as
is_something(&value) -> bool {...}
(which is a common way) and we'd like to pick opposite values, now ther's a must to create unnecessary closure.filter(|value| !is_something(value))
, but instead we could simply write.reject(is_something)
.It's also very useful when a condition is a complex bool expression
The first function reads as
take if is not and if (greater or equal to) and is not and is not
which is much less clear thandrop if is or less than or is or is
Moreover, there's a partition function which acts as a combination of
filter
andreject
but we don't actually havereject
.