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

Remove restriction of bsearch block output type #11212

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions spec/std/array_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ describe "Array" do
it "find the element by using binary search" do
[2, 5, 7, 10].bsearch { |x| x >= 4 }.should eq 5
[2, 5, 7, 10].bsearch { |x| x > 10 }.should be_nil
[2, 5, 7, 10].bsearch { |x| x >= 4 ? 1 : nil }.should eq 5
end

it "find the index by using binary search" do
Expand Down
2 changes: 2 additions & 0 deletions spec/std/range_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ describe "Range" do
(0...ary.size).bsearch { |i| true }.should eq 0
(0...ary.size).bsearch { |i| false }.should eq nil

(0...ary.size).bsearch { |i| ary[i] >= 10 ? 1 : nil }.should eq 4

ary = [0, 100, 100, 100, 200]
(0...ary.size).bsearch { |i| ary[i] >= 100 }.should eq 1

Expand Down
30 changes: 16 additions & 14 deletions src/indexable.cr
Original file line number Diff line number Diff line change
Expand Up @@ -133,40 +133,42 @@ module Indexable(T)
end

# By using binary search, returns the first element
# for which the passed block returns `true`.
# for which the passed block returns a truthy value.
#
# If the block returns `false`, the finding element exists
# behind. If the block returns `true`, the finding element
# is itself or exists in front.
# If the block returns a falsey value, the element to be found lies
# behind. If the block returns a truthy value, the element to be found
# is itself or lies in front.
#
# Binary search needs sorted array, so `self` has to be sorted.
# Binary search needs the collection to be sorted in regards to the search
# criterion.
#
# Returns `nil` if the block didn't return `true` for any element.
# Returns `nil` if the block didn't return a truthy value for any element.
#
# ```
# [2, 5, 7, 10].bsearch { |x| x >= 4 } # => 5
# [2, 5, 7, 10].bsearch { |x| x > 10 } # => nil
# ```
def bsearch(&block : T -> Bool)
def bsearch(&block : T -> _)
bsearch_index { |value| yield value }.try { |index| unsafe_fetch(index) }
end

# By using binary search, returns the index of the first element
# for which the passed block returns `true`.
# for which the passed block returns a truthy value.
#
# If the block returns `false`, the finding element exists
# behind. If the block returns `true`, the finding element
# is itself or exists in front.
# If the block returns a falsey value, the element to be found lies
# behind. If the block returns a truthy value, the element to be found
# is itself or lies in front.
#
# Binary search needs sorted array, so `self` has to be sorted.
# Binary search needs the collection to be sorted in regards to the search
# criterion.
#
# Returns `nil` if the block didn't return `true` for any element.
# Returns `nil` if the block didn't return a truthy value for any element.
#
# ```
# [2, 5, 7, 10].bsearch_index { |x, i| x >= 4 } # => 1
# [2, 5, 7, 10].bsearch_index { |x, i| x > 10 } # => nil
# ```
def bsearch_index(&block : T, Int32 -> Bool)
def bsearch_index(&block : T, Int32 -> _)
(0...size).bsearch { |index| yield unsafe_fetch(index), index }
end

Expand Down
16 changes: 8 additions & 8 deletions src/range/bsearch.cr
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,20 @@
{% end %}

struct Range(B, E)
# By using binary search, returns the first value
# for which the passed block returns `true`.
# By using binary search, returns the first element
# for which the passed block returns a truthy value.
#
# If the block returns `false`, the finding value exists
# behind. If the block returns `true`, the finding value
# is itself or exists in front.
# If the block returns a falsey value, the element to be found lies
# behind. If the block returns a truthy value, the element to be found
# is itself or lies in front.
#
# Returns `nil` if the block didn't return a truthy value for any element.
#
# ```
# (0..10).bsearch { |x| x >= 5 } # => 5
# (0..Float64::INFINITY).bsearch { |x| x ** 4 >= 256 } # => 4
# ```
#
# Returns `nil` if the block didn't return `true` for any value.
def bsearch(&block : B | E -> Bool)
def bsearch(&block : B | E -> _)
from = self.begin
to = self.end

Expand Down