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

Add Enumerable#find_value #14893

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jgaskins
Copy link
Contributor

Fixes #14879

src/enumerable.cr Outdated Show resolved Hide resolved
Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl>
# [1, 2, 3, 4].find_value { |i| i > 8 } # => nil
# [1, 2, 3, 4].find_value(-1) { |i| i > 8 } # => -1
# ```
def find_value(if_none = nil, & : T ->)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be of some benefit to have the method strictly typed rather than leaving the compiler to infer everything. We had a discussion in the Discord server and concluded it would mean having an overload specifically for a nil/no-default case, but I think that would be better overall:

def find_value(if_none : U, & : T -> V) : V forall U, V
def find_value(& : T -> U) : U? forall U

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a fan of explicit types, but this is still type inference. What benefit are you seeing here that I'm not seeing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find that the explicitness of method signatures are more useful even if there is no real difference between them. It's also clear what the return type of the method is as both I and another Crystal user initially misinterpreted the return type as being the value of the enumerable type (i.e. T). When taking into account Enumerable#find which has an identical signature, it makes sense to be explicit here to reduce confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's more explicit, but I don't know if I agree that it reduces confusion. To my eyes, it just looks like a jumble of type placeholders.

Does the doc comment provide insufficient disambiguation between it and find?

screenshot of the documentation for the find_value method. It reads: Yields each value until the first truthy block result and returns that result.

Copy link
Member

@straight-shoota straight-shoota Aug 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think type restrictions are always helpful as they document the expectations of input and ouput types. Even if it's a bit complicated to express.
IMO we should ideally always write down all type restrictions as part of the API documentation.

As a comment on the suggested format, different names T -> V and T -> U are confusing. They're doing the same thing, so both proc types should use the same name for their output type.

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

Successfully merging this pull request may close these issues.

Enumerable method to find the first truthy block result and return that result
5 participants