ml.ruby-lang.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

ruby-core

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
ruby-core@ml.ruby-lang.org

  • 2 participants
  • 4179 discussions
[ruby-core:114626] [Ruby master Bug#18080] Syntax error on one-line pattern matching
by yui-knk (Kaneko Yuichiro) 05 Sep '23

05 Sep '23
Issue #18080 has been updated by yui-knk (Kaneko Yuichiro). It's possible https://github.com/yui-knk/ruby/tree/bugs_18080. However need to notice about inconsistency for one line pattern matching for command call without block, like `[].append 1 => a`. Because this is interpreted as `#append` call with hash (`1 => a`) now, so it's impossible to change the behavior without introducing incompatibility. ```ruby [].append => a [].append in a [].append do end => a [].append do end in a [].append(1) => a [].append(1) in a [].append(1) do end => a [].append(1) do end in a # Only this is interpreted as #append method call with hash argument [].append 1 => a [].append 1 in a [].append 1 do end => a [].append 1 do end in a ``` In my opinion (1) is more clear than (2). (1) Method call without surrounding parameters parenthesis can not be put on left of single line pattern matching (2) Almost all method calls can be on left of single line pattern matching but there is one exception (a) without block (b) without parenthesis for parameters (c) pattern matching with `=>` # Note The inconsistency can be found as Shift/Reduce conflict. In this state, shift derives `arg_value • "=>" arg_value` (hash), on the other hand reduce derives `command_call => p_top_expr_body` (pattern matching). https://github.com/yui-knk/ruby/tree/bugs_18080_2 ``` State 223 shift/reduce conflict on token "=>": 308 args: arg_value • 759 assoc: arg_value • "=>" arg_value First example: $@1 k_return arg_value • "=>" arg_value opt_block_arg "=>" @7 @8 p_top_expr_body opt_terms "end-of-input" Shift derivation $accept ↳ 0: program "end-of-input" ↳ 2: $@1 top_compstmt ↳ 3: top_stmts opt_terms ↳ 5: top_stmt ↳ 7: stmt ↳ 37: expr ↳ 65: command "=>" @7 @8 p_top_expr_body ↳ 97: k_return call_args ↳ 299: assocs opt_block_arg ↳ 757: assoc ↳ 759: arg_value • "=>" arg_value Second example: $@1 k_return arg_value • opt_block_arg "=>" @7 @8 p_top_expr_body opt_terms "end-of-input" Reduce derivation $accept ↳ 0: program "end-of-input" ↳ 2: $@1 top_compstmt ↳ 3: top_stmts opt_terms ↳ 5: top_stmt ↳ 7: stmt ↳ 37: expr ↳ 65: command_call "=>" @7 @8 p_top_expr_body ↳ 82: command ↳ 97: k_return call_args ↳ 298: args opt_block_arg ↳ 308: arg_value • ``` ---------------------------------------- Bug #18080: Syntax error on one-line pattern matching https://bugs.ruby-lang.org/issues/18080#change-104454 * Author: ko1 (Koichi Sasada) * Status: Open * Priority: Normal * ruby -v: 3.1.0dev * Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN ---------------------------------------- One line pattern matching with a method return value with parameters which are not surrounded by parenthesis raises syntax error. I think it is not intentional, but nobu said it's hard to support because of parse.y limitation. ```ruby p do end => a p a #=> nil p(1) do end => a p a #=> 1 p 1 do end => a #=> # syntax error, unexpected =>, expecting end-of-input # end => a # ^~ p 1 do end in a #=> # syntax error, unexpected `in', expecting end-of-input # end in a # ^~ ``` -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:111499] [Ruby master Bug#19281] SyntaxError if first argument of command call has semicolon inside parenthesis
by tompng (tomoya ishida) 04 Sep '23

04 Sep '23
Issue #19281 has been reported by tompng (tomoya ishida). ---------------------------------------- Bug #19281: SyntaxError if first argument of command call has semicolon inside parenthesis https://bugs.ruby-lang.org/issues/19281 * Author: tompng (tomoya ishida) * Status: Open * Priority: Normal * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- These are syntax error ~~~ruby p (1;2),(3),(4) p (;),(),() a.b (1;2),(3),(4) a.b (;),(),() ~~~ I expect it to be syntax ok because the code below is syntax ok. ~~~ruby p (1),(2;3),(4;5) p (),(;),(;) a.b (1),(2;3),(4;5) a.b (),(;),(;) ~~~ It will be easy to traverse sexp if the sexp of first argument is same as others ~~~ruby Ripper.sexp "p (),(),()" # => [:program, [[:command, [:@ident, "p", [1, 0]], [:args_add_block, [[:paren, false], # [:paren, [[:void_stmt]]] [:paren, [[:void_stmt]]], [:paren, [[:void_stmt]]]], false]]]] Ripper.sexp "p (1),(2),(3)" # => [:program, [[:command, [:@ident, "p", [1, 0]], [:args_add_block, [[:paren, [:@int, "1", [1, 3]]], # [:paren, [[:@int, "1", [1, 3]]]] [:paren, [[:@int, "2", [1, 7]]]], [:paren, [[:@int, "3", [1, 11]]]]], false]]]] ~~~ -- https://bugs.ruby-lang.org/
3 2
0 0
[ruby-core:114620] [Ruby master Feature#19075] Binary searching for the last element
by sawa (Tsuyoshi Sawada) 04 Sep '23

04 Sep '23
Issue #19075 has been updated by sawa (Tsuyoshi Sawada). When we want to reverse the direction in any sense, such as the direction of search, in my understanding, it's Ruby's custom to use the word "reverse" or a prefix "r": `Enumerable#revserse_each` `Array#rindex` `String#rindex` `String#rjust` `String#rpartition` `String#rstrip` To be consistent, I think it is better to have independent methods as in the original proposal, but with method names like: `reverse_bsearch` `bsearch_rindex` ---------------------------------------- Feature #19075: Binary searching for the last element https://bugs.ruby-lang.org/issues/19075#change-104447 * Author: kyanagi (Kouhei Yanagita) * Status: Open * Priority: Normal ---------------------------------------- My latest proposal is https://bugs.ruby-lang.org/issues/19075#note-6. I will leave the initial proposal below. --- PR: https://github.com/ruby/ruby/pull/6611 (I'm going to talk about `Array` here, but the same argument can be made for `Range`. If `Array#bsearch_last` is acceptable, I will work also for `Range`.) Ruby's bsearch returns the first element which satisfies the given block. ```ruby # Search the first element greater than 18 array = [10, 15, 20, 25] array.bsearch { |x| x > 18 } # => 20 ``` If we want the last element, we need to invert the condition and step backward. ```ruby # Search the last element less than 18 array = [10, 15, 20, 25] index = array.bsearch_index { |x| !(x < 18) } array[index-1] # => 15 ``` Of course, we need to consider `nil` and the boundary. ```ruby # Search the last element less than 100 index = array.bsearch_index { |x| !(x < 100) } # => nil if index.nil? array.last # => 25 else array[index-1] end ``` ```ruby # Search the last element less than 0 index = array.bsearch_index { |x| !(x < 0) } # => 0 if index.nil? array.last elsif index == 0 nil else array[index-1] end ``` This is where mistakes can easily be made, so I propose `Array#bsearch_last` and `Array#bsearch_last_index`. `Array#bsearch_last` returns the last element which satisfies the given block. `Array#bsearch` requires that all false-evaluating elements precede all true-evaluating elements. As is clear from the meaning of the method, conversely to `bsearch`, `bsearch_last` requires that all true-evaluating elements precede all false-evaluating elements. (If `bsearch_last` is acceptable, the name "find-minimum mode" should be changed.) ```ruby array = [10, 15, 20, 25] array.bsearch_last { |x| x < 18 } # => 15 array.bsearch_last { |x| x < 100 } # => 25 array.bsearch_last { |x| x < 0 } # => nil ``` There are several possible options for find-any mode. (1) `bsearch_last` does not support find-any mode. A block for `bsearch_last` must return `true`, `false` or `nil`. ``` [1, 2, 3].bsearch_last { 0 } # => TypeError ``` My pull request tentatively includes this implementation. (2) `bsearch_last` supports find-any mode and it behaves like `bsearch`. `bsearch` with find-any mode returns an element, for which the block returns zero. If multiple elements satisfy the condition, it is not determined which of them will be returned. It is conceivable that `bsearch_last` behaves in the same way as `bsearch`. ``` # current behavior # It is not specified whether `:b`, `:c`, or `:d` is returned. [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :c] ``` (3) `bsearch_last` supports find-any mode and returns the last element. Make `bsearch` return the first element. Change the behavior of `bsearch` to return the first element for which the block returns zero. `bsearch_last` returns the last element for which the block returns zero. ``` # Change it like this: [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :b] [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch_last { |a, b| 2 <=> a } # => [2, :d] ``` (If this option is adopted, the name "find-any mode" should be renamed.) -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:114619] [Ruby master Feature#19075] Binary searching for the last element
by Dan0042 (Daniel DeLorme) 04 Sep '23

04 Sep '23
Issue #19075 has been updated by Dan0042 (Daniel DeLorme). > ``` > a = [2, 3, 5, 7, 11] > a.bsearch {|x| x >= 6 } # => 7 > a.bsearch(target: :first) {|x| x >= 6 } # same as a.bsearch { ... } > a.bsearch(target: :last) {|x| x <= 6 } # => 5 > a.bsearch(target: :first) {|x| 0 } # => 2 > a.bsearch(target: :last) {|x| 0 } # => 11 > ``` I like this implementation. But for naming, personally I find `target: :last` to be confusing. If I suddenly read that in code I wouldn't be able to guess what it does; I would have to refer to the documentation. I don't really have a good alternative. Maybe `bsearch(find: :last)` ?_? ---------------------------------------- Feature #19075: Binary searching for the last element https://bugs.ruby-lang.org/issues/19075#change-104446 * Author: kyanagi (Kouhei Yanagita) * Status: Open * Priority: Normal ---------------------------------------- My latest proposal is https://bugs.ruby-lang.org/issues/19075#note-6. I will leave the initial proposal below. --- PR: https://github.com/ruby/ruby/pull/6611 (I'm going to talk about `Array` here, but the same argument can be made for `Range`. If `Array#bsearch_last` is acceptable, I will work also for `Range`.) Ruby's bsearch returns the first element which satisfies the given block. ```ruby # Search the first element greater than 18 array = [10, 15, 20, 25] array.bsearch { |x| x > 18 } # => 20 ``` If we want the last element, we need to invert the condition and step backward. ```ruby # Search the last element less than 18 array = [10, 15, 20, 25] index = array.bsearch_index { |x| !(x < 18) } array[index-1] # => 15 ``` Of course, we need to consider `nil` and the boundary. ```ruby # Search the last element less than 100 index = array.bsearch_index { |x| !(x < 100) } # => nil if index.nil? array.last # => 25 else array[index-1] end ``` ```ruby # Search the last element less than 0 index = array.bsearch_index { |x| !(x < 0) } # => 0 if index.nil? array.last elsif index == 0 nil else array[index-1] end ``` This is where mistakes can easily be made, so I propose `Array#bsearch_last` and `Array#bsearch_last_index`. `Array#bsearch_last` returns the last element which satisfies the given block. `Array#bsearch` requires that all false-evaluating elements precede all true-evaluating elements. As is clear from the meaning of the method, conversely to `bsearch`, `bsearch_last` requires that all true-evaluating elements precede all false-evaluating elements. (If `bsearch_last` is acceptable, the name "find-minimum mode" should be changed.) ```ruby array = [10, 15, 20, 25] array.bsearch_last { |x| x < 18 } # => 15 array.bsearch_last { |x| x < 100 } # => 25 array.bsearch_last { |x| x < 0 } # => nil ``` There are several possible options for find-any mode. (1) `bsearch_last` does not support find-any mode. A block for `bsearch_last` must return `true`, `false` or `nil`. ``` [1, 2, 3].bsearch_last { 0 } # => TypeError ``` My pull request tentatively includes this implementation. (2) `bsearch_last` supports find-any mode and it behaves like `bsearch`. `bsearch` with find-any mode returns an element, for which the block returns zero. If multiple elements satisfy the condition, it is not determined which of them will be returned. It is conceivable that `bsearch_last` behaves in the same way as `bsearch`. ``` # current behavior # It is not specified whether `:b`, `:c`, or `:d` is returned. [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :c] ``` (3) `bsearch_last` supports find-any mode and returns the last element. Make `bsearch` return the first element. Change the behavior of `bsearch` to return the first element for which the block returns zero. `bsearch_last` returns the last element for which the block returns zero. ``` # Change it like this: [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :b] [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch_last { |a, b| 2 <=> a } # => [2, :d] ``` (If this option is adopted, the name "find-any mode" should be renamed.) -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:114488] [Ruby master Bug#19847] Cannot install Ruby 3.2.2 on Windows using Visual Studio 2019
by dmwhitne (David Whitney) 01 Sep '23

01 Sep '23
Issue #19847 has been reported by dmwhitne (David Whitney). ---------------------------------------- Bug #19847: Cannot install Ruby 3.2.2 on Windows using Visual Studio 2019 https://bugs.ruby-lang.org/issues/19847 * Author: dmwhitne (David Whitney) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mswin64_140] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- I am attempting to build/install Ruby 3.2.2 open-source code on Windows using Visual Studio 2019. These are the steps I followed: Using an x64 Native Tools Command Prompt (for Visual Studio 2019).. 1. cd C:\tmp\ruby-3.2.2 2. win32\configure.bat --prefix=C:\Ruby-3.2.2 --target=x64-mswin64 --disable-install-doc 3. nmake 4. nmake install The error (on Step 4): Downloading bundled gem files... `RubyGems' were not loaded. `error_highlight' was not loaded. `did_you_mean' was not loaded. `syntax_suggest' was not loaded. c:/tmp/ruby-3.2.2/tool/downloader.rb:4:in `require': cannot load such file -- fileutils (LoadError) from c:/tmp/ruby-3.2.2/tool/downloader.rb:4:in `<top (required)>' from -e:in `require' NMAKE : fatal error U1077: 'c:\tmp\RUBY-3~1.2\ruby.exe' : return code '0x1' Stop. Is this a bug, or operator error? -- https://bugs.ruby-lang.org/
2 2
0 0
[ruby-core:114433] [Ruby master Bug#19843] Promote bigdecimal as bundled gems at Ruby 3.4
by hsbt (Hiroshi SHIBATA) 01 Sep '23

01 Sep '23
Issue #19843 has been reported by hsbt (Hiroshi SHIBATA). ---------------------------------------- Bug #19843: Promote bigdecimal as bundled gems at Ruby 3.4 https://bugs.ruby-lang.org/issues/19843 * Author: hsbt (Hiroshi SHIBATA) * Status: Open * Priority: Normal * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- I triaged target list for bundled gems at https://bugs.ruby-lang.org/issues/19351. After that, I resolved bigdecimal dependency from our test suite at https://github.com/ruby/ruby/commit/3ef6364a988ab24ca7fdbb7d1b6840b2a40f1466 I propose to promote `bigdecimal` as bundled gems at Ruby 3.4. @mrkn Is it okay? I will add `bigdecimal` to `Gem::BUNDLED_GEMS::SINCE` for Ruby 3.3.0-preview2. -- https://bugs.ruby-lang.org/
3 4
0 0
[ruby-core:114612] [Ruby master Bug#16951] Consistently referer dependencies
by hsbt (Hiroshi SHIBATA) 01 Sep '23

01 Sep '23
Issue #16951 has been updated by hsbt (Hiroshi SHIBATA). >would it be possible to get an update on this? It's difficult to answer. All of dependencies are maintainer's convenience basically. I started to suggest to add dependency explicitly for gem authors at https://bugs.ruby-lang.org/issues/19776. You can see this suggested gems at https://github.com/ruby/ruby/blob/master/lib/bundled_gems.rb#L2. On the other hand, I have no plan to add `net-http` into `Gem::BUNDLED_GEMS::SINCE` because `net-http` provides core feature of RubyGems. So, we can't remove it from default gems. ---------------------------------------- Bug #16951: Consistently referer dependencies https://bugs.ruby-lang.org/issues/16951#change-104440 * Author: vo.x (Vit Ondruch) * Status: Closed * Priority: Normal * Assignee: hsbt (Hiroshi SHIBATA) * ruby -v: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux] * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN ---------------------------------------- It seems that the default gems interdependencies in Ruby are mess. Years ago, when JSON was merged into StdLib, there was big movement and everybody dropped their references to JSON "because it is part of StdLib and therefore it is not needed". I always thought that removing the references was mistake. Now, there are other interesting cases. Let me name two I know about: 1) REXML is going to be removed from default gems in Ruby 2.8, so some packages already started to introduce the dependency explicitly [1]. So once somebody uses Kramdown on older Ruby, the external REXML of whatever version is going to be used. 2) There are also gems in StdLib, such as IRB, which are specifying their dependencies in .gemspec file. This is unfortunately causing very inconsistent user experience, depending if RubyGems are enabled/disabled, if one is using Bundler or not, if somebody explicitly states something somewhere and what dependencies are transitively pulled in. I would really appreciate, if Ruby upstream finally paid attention to this problem. My suggestion is that if some gem depends on some other gem, this dependency should be always explicitly stated in the .gemspec file. This would provide clear precedence and guideline to others. This would save all possible surprises and hidden issues, suddenly using dependency of different version, which is pulled in transitively. [1]: https://github.com/gettalong/kramdown/commit/c1aa6ad98fab589050ab8e82897ec4… -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:114276] [Ruby master Bug#19784] String#delete_prefix! problem
by inversion (Yura Babak) 01 Sep '23

01 Sep '23
Issue #19784 has been reported by inversion (Yura Babak). ---------------------------------------- Bug #19784: String#delete_prefix! problem https://bugs.ruby-lang.org/issues/19784 * Author: inversion (Yura Babak) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Here is the snipped and the question is in the comments: ``` ruby fp = 'with_BOM_16.txt' body = File.read(fp).force_encoding('UTF-8') p body # "\xFF\xFE1\u00001\u0000" p body.start_with?("\xFF\xFE") # true body.delete_prefix!("\xFF\xFE") # !!! why doesn't work? p body # "\xFF\xFE1\u00001\u0000" p body.start_with?("\xFF\xFE") # true body[0, 2] = '' p body # "1\u00001\u0000" p body.start_with?("\xFF\xFE") # false ``` Works same on Linux (ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]) and Windows (ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mingw-ucrt]) -- https://bugs.ruby-lang.org/
6 9
0 0
[ruby-core:114607] [Ruby master Feature#19075] Add Array#bsearch_last and #bsearch_last_index
by kyanagi (Kouhei Yanagita) 31 Aug '23

31 Aug '23
Issue #19075 has been updated by kyanagi (Kouhei Yanagita). > I consider that the return value in this case was indeterministic, and this assertion is too implementation specific. I agree. I think this assertion is not based on the specification. ---------------------------------------- Feature #19075: Add Array#bsearch_last and #bsearch_last_index https://bugs.ruby-lang.org/issues/19075#change-104430 * Author: kyanagi (Kouhei Yanagita) * Status: Open * Priority: Normal ---------------------------------------- PR: https://github.com/ruby/ruby/pull/6611 (I'm going to talk about `Array` here, but the same argument can be made for `Range`. If `Array#bsearch_last` is acceptable, I will work also for `Range`.) Ruby's bsearch returns the first element which satisfies the given block. ```ruby # Search the first element greater than 18 array = [10, 15, 20, 25] array.bsearch { |x| x > 18 } # => 20 ``` If we want the last element, we need to invert the condition and step backward. ```ruby # Search the last element less than 18 array = [10, 15, 20, 25] index = array.bsearch_index { |x| !(x < 18) } array[index-1] # => 15 ``` Of course, we need to consider `nil` and the boundary. ```ruby # Search the last element less than 100 index = array.bsearch_index { |x| !(x < 100) } # => nil if index.nil? array.last # => 25 else array[index-1] end ``` ```ruby # Search the last element less than 0 index = array.bsearch_index { |x| !(x < 0) } # => 0 if index.nil? array.last elsif index == 0 nil else array[index-1] end ``` This is where mistakes can easily be made, so I propose `Array#bsearch_last` and `Array#bsearch_last_index`. `Array#bsearch_last` returns the last element which satisfies the given block. `Array#bsearch` requires that all false-evaluating elements precede all true-evaluating elements. As is clear from the meaning of the method, conversely to `bsearch`, `bsearch_last` requires that all true-evaluating elements precede all false-evaluating elements. (If `bsearch_last` is acceptable, the name "find-minimum mode" should be changed.) ```ruby array = [10, 15, 20, 25] array.bsearch_last { |x| x < 18 } # => 15 array.bsearch_last { |x| x < 100 } # => 25 array.bsearch_last { |x| x < 0 } # => nil ``` There are several possible options for find-any mode. (1) `bsearch_last` does not support find-any mode. A block for `bsearch_last` must return `true`, `false` or `nil`. ``` [1, 2, 3].bsearch_last { 0 } # => TypeError ``` My pull request tentatively includes this implementation. (2) `bsearch_last` supports find-any mode and it behaves like `bsearch`. `bsearch` with find-any mode returns an element, for which the block returns zero. If multiple elements satisfy the condition, it is not determined which of them will be returned. It is conceivable that `bsearch_last` behaves in the same way as `bsearch`. ``` # current behavior # It is not specified whether `:b`, `:c`, or `:d` is returned. [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :c] ``` (3) `bsearch_last` supports find-any mode and returns the last element. Make `bsearch` return the first element. Change the behavior of `bsearch` to return the first element for which the block returns zero. `bsearch_last` returns the last element for which the block returns zero. ``` # Change it like this: [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :b] [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch_last { |a, b| 2 <=> a } # => [2, :d] ``` (If this option is adopted, the name "find-any mode" should be renamed.) -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:114606] [Ruby master Feature#19075] Add Array#bsearch_last and #bsearch_last_index
by nobu (Nobuyoshi Nakada) 31 Aug '23

31 Aug '23
Issue #19075 has been updated by nobu (Nobuyoshi Nakada). The PR fails at spec/ruby/core/array/bsearch_index_spec.rb:67. ```ruby it "returns the middle element when block always returns zero" do @array.bsearch_index { |x| 0 }.should == 2 end ``` I consider that the return value in this case was indeterministic, and this assertion is too implementation specific. ---------------------------------------- Feature #19075: Add Array#bsearch_last and #bsearch_last_index https://bugs.ruby-lang.org/issues/19075#change-104429 * Author: kyanagi (Kouhei Yanagita) * Status: Open * Priority: Normal ---------------------------------------- PR: https://github.com/ruby/ruby/pull/6611 (I'm going to talk about `Array` here, but the same argument can be made for `Range`. If `Array#bsearch_last` is acceptable, I will work also for `Range`.) Ruby's bsearch returns the first element which satisfies the given block. ```ruby # Search the first element greater than 18 array = [10, 15, 20, 25] array.bsearch { |x| x > 18 } # => 20 ``` If we want the last element, we need to invert the condition and step backward. ```ruby # Search the last element less than 18 array = [10, 15, 20, 25] index = array.bsearch_index { |x| !(x < 18) } array[index-1] # => 15 ``` Of course, we need to consider `nil` and the boundary. ```ruby # Search the last element less than 100 index = array.bsearch_index { |x| !(x < 100) } # => nil if index.nil? array.last # => 25 else array[index-1] end ``` ```ruby # Search the last element less than 0 index = array.bsearch_index { |x| !(x < 0) } # => 0 if index.nil? array.last elsif index == 0 nil else array[index-1] end ``` This is where mistakes can easily be made, so I propose `Array#bsearch_last` and `Array#bsearch_last_index`. `Array#bsearch_last` returns the last element which satisfies the given block. `Array#bsearch` requires that all false-evaluating elements precede all true-evaluating elements. As is clear from the meaning of the method, conversely to `bsearch`, `bsearch_last` requires that all true-evaluating elements precede all false-evaluating elements. (If `bsearch_last` is acceptable, the name "find-minimum mode" should be changed.) ```ruby array = [10, 15, 20, 25] array.bsearch_last { |x| x < 18 } # => 15 array.bsearch_last { |x| x < 100 } # => 25 array.bsearch_last { |x| x < 0 } # => nil ``` There are several possible options for find-any mode. (1) `bsearch_last` does not support find-any mode. A block for `bsearch_last` must return `true`, `false` or `nil`. ``` [1, 2, 3].bsearch_last { 0 } # => TypeError ``` My pull request tentatively includes this implementation. (2) `bsearch_last` supports find-any mode and it behaves like `bsearch`. `bsearch` with find-any mode returns an element, for which the block returns zero. If multiple elements satisfy the condition, it is not determined which of them will be returned. It is conceivable that `bsearch_last` behaves in the same way as `bsearch`. ``` # current behavior # It is not specified whether `:b`, `:c`, or `:d` is returned. [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :c] ``` (3) `bsearch_last` supports find-any mode and returns the last element. Make `bsearch` return the first element. Change the behavior of `bsearch` to return the first element for which the block returns zero. `bsearch_last` returns the last element for which the block returns zero. ``` # Change it like this: [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :b] [[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch_last { |a, b| 2 <=> a } # => [2, :d] ``` (If this option is adopted, the name "find-any mode" should be renamed.) -- https://bugs.ruby-lang.org/
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • ...
  • 418
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.