From: "kddnewton (Kevin Newton) via ruby-core" Date: 2025-02-14T17:19:30+00:00 Subject: [ruby-core:121053] [Ruby master Feature#21135] Feature request: Enumerable.compare_count Issue #21135 has been updated by kddnewton (Kevin Newton). We already have lazy enumerators, so I think your request can be simplified a bit by taking advantage of that and defining Enumerator::Lazy#length to return an object that knows how to compare itself to other stuff. Something like: ```ruby class Enumerator class Lazy class Length def initialize(enum) @enum = enum end def force = @enum.to_a.length def <=>(value) = force <=> value def <(value) = value >= 0 && @enum.take(value).to_a.length < value def <=(value) = value >= 0 && @enum.take(value + 1).to_a.length <= value def >(value) = value <= 0 || @enum.take(value + 1).to_a.length > value def >=(value) = value <= 0 || @enum.take(value).to_a.length == value def ==(value) = value >= 0 && @enum.take(value + 1).to_a.length == value def !=(value) = value < 0 || @enum.take(value + 1).to_a.length != value end def length = Length.new(self) end end ``` In your example, instead of `d.compare_count(op, x)` this would instead be `d.lazy.length.public_send(op, x)`, and instead of `d.compare_count(op, x){|p| Prime.prime?(p)}` it would instead be `d.lazy.select { |p| Prime.prime?(p) }.length.public_send(op, x)`. I don't know if this is applicable enough to other projects that it would merit being in core, but I _do_ think this would be simpler than the requested method. ---------------------------------------- Feature #21135: Feature request: Enumerable.compare_count https://bugs.ruby-lang.org/issues/21135#change-111968 * Author: Student (Nathan Zook) * Status: Open ---------------------------------------- Enumerables at times can be quite expensive to complete expand. If all is desired is to compare the count, we can terminate the enumeration once the result is known. The functionality that I envision, if implemented in ruby, might look like this: ```ruby module Enumerable def compare_count(operation, standard, &blk) case operation when :< compare_count_lt(standard, &blk) when :>= !compare_count_lt(standard, &blk) when :> compare_count_spaceship(standard, &blk) == 1 when :<= compare_count_spaceship(standard, &blk) != 1 when :== compare_count_spaceship(standard, &blk) == 0 when :!= compare_count_spaceship(standard, &blk) != 0 end end def compare_count_lt(standard, &blk) truncate_count(standard - 1, &blk) < standard end def compare_count_spaceship(standard, &blk) truncate_count(standard, &blk) <=> standard end def truncate_count(limit, &blk) return 0 if limit < 0 found = 0 each do |ele| found += 1 unless blk && !yield(ele) break if found > limit end found end end class Demo include Enumerable attr_reader :capacity attr_reader :cnt def initialize(capacity) @capacity = capacity end def each @cnt = 0 while cnt < capacity @cnt += 1 yield cnt end end end %i{< <= >= > == !=}.each do |op| d = Demo.new(3) (-1..5).each do |x| puts [op, x, d.compare_count(op, x), d].inspect end end require 'prime' %i{< <= >= > == !=}.each do |op| d = Demo.new(6) (-1..5).each do |x| puts [op, x, d.compare_count(op, x){|p| Prime.prime?(p)} , d].inspect end end ``` ``` [:<, -1, false, #] [:<, 0, false, #] [:<, 1, false, #] [:<, 2, false, #] [:<, 3, false, #] [:<, 4, true, #] [:<, 5, true, #] [:<=, -1, false, #] [:<=, 0, false, #] [:<=, 1, false, #] [:<=, 2, false, #] [:<=, 3, true, #] [:<=, 4, true, #] [:<=, 5, true, #] [:>=, -1, true, #] [:>=, 0, true, #] [:>=, 1, true, #] [:>=, 2, true, #] [:>=, 3, true, #] [:>=, 4, false, #] [:>=, 5, false, #] [:>, -1, true, #] [:>, 0, true, #] [:>, 1, true, #] [:>, 2, true, #] [:>, 3, false, #] [:>, 4, false, #] [:>, 5, false, #] [:==, -1, false, #] [:==, 0, false, #] [:==, 1, false, #] [:==, 2, false, #] [:==, 3, true, #] [:==, 4, false, #] [:==, 5, false, #] [:!=, -1, true, #] [:!=, 0, true, #] [:!=, 1, true, #] [:!=, 2, true, #] [:!=, 3, false, #] [:!=, 4, true, #] [:!=, 5, true, #] [:<, -1, false, #] [:<, 0, false, #] [:<, 1, false, #] [:<, 2, false, #] [:<, 3, false, #] [:<, 4, true, #] [:<, 5, true, #] [:<=, -1, false, #] [:<=, 0, false, #] [:<=, 1, false, #] [:<=, 2, false, #] [:<=, 3, true, #] [:<=, 4, true, #] [:<=, 5, true, #] [:>=, -1, true, #] [:>=, 0, true, #] [:>=, 1, true, #] [:>=, 2, true, #] [:>=, 3, true, #] [:>=, 4, false, #] [:>=, 5, false, #] [:>, -1, true, #] [:>, 0, true, #] [:>, 1, true, #] [:>, 2, true, #] [:>, 3, false, #] [:>, 4, false, #] [:>, 5, false, #] [:==, -1, false, #] [:==, 0, false, #] [:==, 1, false, #] [:==, 2, false, #] [:==, 3, true, #] [:==, 4, false, #] [:==, 5, false, #] [:!=, -1, true, #] [:!=, 0, true, #] [:!=, 1, true, #] [:!=, 2, true, #] [:!=, 3, false, #] [:!=, 4, true, #] [:!=, 5, true, #] ``` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/