Skip to content
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

Array#reject! shouldn't return Nil #4994

Closed
tbrand opened this issue Sep 17, 2017 · 12 comments
Closed

Array#reject! shouldn't return Nil #4994

tbrand opened this issue Sep 17, 2017 · 12 comments

Comments

@tbrand
Copy link

tbrand commented Sep 17, 2017

Reproducible code

arr = [ 1, 2, 4, 5 ]
arr
  .reject! { |e| e%2 == 0 }
  .reject! { |e| e == 1 }

puts arr

When execute this code in ruby, it returns [5].
In Crystal, it raises a following error.

Error in filename:2: undefined method 'reject!' for Nil (compile-time type is (Array(Int32) | Nil))

The problem is not the compatibility, but the usability.
In many real cases, we use such methods in chains.
So reject! should return an empty array when reject! removes all of the elements.
Needless to say, using not_nil! is not safety.

Thanks

Crystal version: 0.23.1
Sierra 10.12.6
@vladfaust
Copy link
Contributor

arr = [1, 2, 4, 5]
arr = arr
  .reject { |e| e % 2 == 0 }
  .reject { |e| e == 1 }

puts arr # => [5]

This shouldn't cause any sensible performance impact.

@tbrand
Copy link
Author

tbrand commented Sep 17, 2017

Hmm...
OK, I'll modify my code like that.:+1:

@tbrand tbrand closed this as completed Sep 17, 2017
@asterite
Copy link
Member

@tbrand Actually, Crystal is safer here. If arr is not known to you, this can happen:

# Ruby
arr = [1, 5]
arr
  .reject! { |e| e % 2 == 0 }
  .reject! { |e| e == 1 }

puts arr

Output:

bar.cr:4:in `<main>': undefined method `reject!' for nil:NilClass (NoMethodError)

Exactly the same error Crystal gives you, but Ruby tells you at runtime time, Crystal at compile time.

There's no need to use reject, there's always try:

arr = [1, 2, 4, 5]
arr
  .reject! { |e| e % 2 == 0 }
  .try &.reject! { |e| e == 1 }

puts arr

@tbrand
Copy link
Author

tbrand commented Sep 17, 2017

Ruby tells you at runtime time, Crystal at compile time.

💯

There's no need to use reject, there's always try:

try is the best!! Thanks!! (I forgot the existence...)

@oprypin
Copy link
Member

oprypin commented Sep 17, 2017

Hold on... why would reject! ever return nil? That makes no sense. (Yes, it's described in the documentation, but why do that?)

@asterite
Copy link
Member

That way you know if reject! made changes or not.

@oprypin
Copy link
Member

oprypin commented Sep 17, 2017

OK but there are other ways to get this information. Other methods don't have such a quirk.
So, why do that?

@asterite
Copy link
Member

Carried from Ruby. How else would you do that? Maybe that info is not important...?

@oprypin
Copy link
Member

oprypin commented Sep 17, 2017

Well, the obvious thing is to return self, as almost every other ! method does. But whatever, this is not worth arguing about.

@oprypin
Copy link
Member

oprypin commented Sep 17, 2017

By the way, how to get that information -- get size before and size after

@asterite
Copy link
Member

I think it's better to always return self so chaining is possible. It's true that the return value is almost meaningless.

maxpowa added a commit to maxpowa/crystal that referenced this issue Oct 20, 2017
Modifies Array based on discussion in crystal-lang#4994. `Array#reject!`, `Array#select!`, and `Array#compact!` now return self in all scenarios.
maxpowa added a commit to maxpowa/crystal that referenced this issue Oct 20, 2017
Modifies Array based on discussion in crystal-lang#4994. `Array#reject!`, `Array#select!`, and `Array#compact!` now return self in all scenarios.
@AlexWayfer
Copy link
Contributor

Now we need the same changes in Ruby 😅
(I'm sorry, a sore subject for me)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants