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
Remove delete_if #9878
Remove delete_if #9878
Conversation
Let's first have a proper discussion on how to proceed with this. Please open an issue and describe your proposal. Only when that's come to a conclusion, it's time to implement it. Proposals tend to change over time. Starting a discussion whit a PR (or rather jumping from one PR to another) has proven to be an inefficient means to communicate about proposed changes. |
Sorry @straight-shoota, I was jumping on work mentioned in the discussion here #9856, specifically this comment |
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.
Thank you!
Even though we are not 1.0 should there be a depreciation warning for this? |
Instead of using
its faster to do:
or
I see this kind of unnecessary|expensive use of |
@jzakiya Why not just |
I was pointing out how to improve that code snippet by eliminating using I suspect many (younger) programmers don't really understand even|odd of an integer is merely if the I grew up as a hardware engineer, and this is what you do in hardware, branch on the Yes, you can (should?) use |
An option can be to have a 0.36.0 before 1.0 in order to have the deprecation warnings. After that, we will have a clean, 0 deprecations for 1.0. The deprecation warnings are important to make the Crystal upgrade experience a breeze @wontruefree . I agree with you that it doesn't feel right to have warnings for a "definitive" 1.0 API. |
@j8r the next version is 1.0, that's not discussable |
@jzakiya LLVM should optimise that operation in release and as http://duriansoftware.com/joe/Optimizing-is-multiple-checks-with-modular-arithmetic.html |
@jzakiya I copied the test from |
Thank you @caspiano, and I agree they are the clearest for someone reading the code. I am willing (with others) to do a thorough (as possible that I can do) review of Crystal's codebase to identify instances to use Or I (and others) can first identify such instances to log for change for future consideration. While writing this, I think it would be more manageable to create a list of instances first, so people can review them to insure changing their semantics won't create unexpected edge cases for their particular use cases, just to be careful. Addition: |
You won't find such instances except in tests, and there it doesn't matter. |
@bcardiff following from your comment here From a manual code search on github, I saw around ~80 instances of |
71ef6bd
to
af8c772
Compare
So @asterite for clarity, you don't favor even changing test code? I think even changing test code instances is worth doing, because you would be reinforcing |
af8c772
to
8cb3692
Compare
@jzakiya updated. I doubt anyone's going to stop you improving the tests. However this is best discussed on a seperate PR. |
Will do. |
# See also: `Deque#reject`. | ||
def reject! | ||
internal_delete { |e| yield e } | ||
self |
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.
Let's make return self or nil as in Hash.
Ref: #9856 (comment)
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'd prefer to change Hash#reject!
to be non-nilable instead. There's really not much reason to return nil
and it breaks method chaining. If you need to know whether an item was removed, you can keep track of whether the block ever returns false
as demonstrated in #9879 (comment)
That clearly communicates what's going on and avoids having to do some nasty nil-checks when chaning calls. I doubt there are many use cases for the nilable return type anyway.
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.
Changing Hash#reject!
to return always self would be a silent breaking-change.
Ruby returns self or nil on {Array, Hash}#reject!
.
tap
can be used to perform chaining if wanted. c.tap(&.reject!(...)).foo
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.
Changing Hash#reject! to return always self would be a silent breaking-change.
Yes, that's unfortunate. We don't necessarily have to change it, at least not right now. But I would not introduce the same weird return type for new methods.
tap can be used to perform chaining if wanted. c.tap(&.reject!(...)).foo
This clearly shows that it doesn't make any sense to have #reject!
return self
as an indicator for an item being deleted. Returning Bool
would be sufficient if such a return value is desired. Otherwise it should just be self
always.
Even nil
always is better than self | nil
.
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.
Should we then update Array#reject!
to also return self | nil
?
I don't see a particularly good reason for the inconsistency between these interfaces besides least astonishment coming from ruby. I think the return type of self
is better purely for the benefit of simply chaining methods.
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.
Ok, let's keep reject! : self
then. We will change the hash#reject!
in another PR.... I hope this breaking-change will not haunt us later...
Implementing changes referenced by @asterite in #9856
Hash#delete_if
Deque#delete_if
Deque#reject!
Deque#select!