-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
replace the API of replace #25697
replace the API of replace #25697
Conversation
I also dislike the current meaning of But this new interpretation makes me nervous. This is a case where substituting a different value makes something totally different happen, which is generally a bad idea. If the value you have just happens to be |
I think I agree with you. In the "secondary" API which uses pairs, I also had to deal with this subtlety, and use a |
Yes, using |
Another possibility would be to have a keyword |
Good idea. I think better apply the minimal change to stop treating |
Shouldn't dropping arguments equal to a value be a job for |
Yes, dropping elements isn't strictly necessary for |
0284ab3
to
62e8ae5
Compare
Updated accordingly. I kept the first commit, to re-use its code if we want to evolve the API with "remove" in the future, but this should be squashed on merge.
I guess it would be more efficient to use one pass with the possible "remove" functionality in |
test/sets.jl
Outdated
@test replace(x -> x === nothing ? 0 : Some(nothing), a) == [nothing, nothing, 0, nothing] | ||
@test replace(x -> x === nothing ? 0 : nothing, a) == [1, 2, 0, 4] | ||
@test replace!(x -> x !== nothing ? Some(nothing) : nothing, a) == [nothing, nothing, nothing, nothing] | ||
# test nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it useful to keep these tests now that nothing
is no longer special? Otherwise, looks good!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hesitated and thought it doesn't hurt to keep those, but I now think it's better to shrink these (maybe keep a couple such tests to be sure nothing
is not treated specially).
base/set.jl
Outdated
will be used as a replacement for `x`. | ||
Replace each element `x` in collection `A` by `new(x)`. | ||
If `count` is specified, then replace at most `count` values in total | ||
(when `new(x) === x`, this does not count as a replacement). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rephrase this as something like "(replacements being defined as new(x) !== x
)"?
62e8ae5
to
f19586e
Compare
Updated according to @nalimilan's comments. I think this should be good to go. I will be away from computer for one week (with possibly no internet access), feel free to merge or to update the branch if needed (in particular if the final feature freeze happens within this week). |
@@ -591,15 +591,14 @@ Set([0, 2, 3]) | |||
""" | |||
replace!(A, old_new::Pair...; count::Integer=typemax(Int)) = _replace!(A, eltype(A), count, old_new) | |||
|
|||
# we use this wrapper because using directly eltype(A) as the type | |||
# parameter below for Some degrades performance | |||
function _replace!(A, ::Type{K}, count::Integer, old_new::Tuple{Vararg{Pair}}) where K |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like we can drop K
now too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably, and I also wanted to check if with this new version we could get rid of this intermediate function altogether without performance hit, but was lacking time. I will come to it eventually.
I wonder whether we should just deprecate these methods in favor of |
Actually there's one difference between that |
This implements @nalimilan's great idea, to modify the API of
replace
:replace(a, 1=>nothing)
means to delete1
replace(a, 1=>Some(nothing))
means to replace1
by nothingreplace(iseven(x) ? 2x : x==1 ? nothing : x, a)
means replacex
by2x
ifiseven(x)
and delete1
This makes the usual case where one wants to replace (not delete) more intuitive, as there is no need to use
nothing
in the higher order function of the 3rd example (you just return the argument); as a side-effect, I could observe nice speed-up, by more than 50% in some cases.This is very (too?) late in the release process, but hopefully this can be considered, as I think this improves significantly the API. We probably don't need to make a deprecation, as this function has been introduced very recently.
Note that this slighly change the meaning of
count
: before, if the update function was returning the argument instead ofnothing
, it would count as a 1 replacement, now it doesn't.WIP: docstrings for
replace
needs updating (done forreplace!
), and needs tests for deletion.