From: "Student (Nathan Zook) via ruby-core" <ruby-core@...>
Date: 2025-02-17T18:17:37+00:00
Subject: [ruby-core:121091] [Ruby master Feature#21135] Feature request: Enumerable.compare_count

Issue #21135 has been updated by Student (Nathan Zook).


I had indeed forgotten about Enumerable::Lazy. There is a more general solution, which I am working up.  Please close

----------------------------------------
Feature #21135: Feature request: Enumerable.compare_count
https://bugs.ruby-lang.org/issues/21135#change-112010

* 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, #<Demo:0x034d567c @capacity=3>]
[:<, 0, false, #<Demo:0x034d567c @capacity=3>]
[:<, 1, false, #<Demo:0x034d567c @capacity=3, @cnt=1>]
[:<, 2, false, #<Demo:0x034d567c @capacity=3, @cnt=2>]
[:<, 3, false, #<Demo:0x034d567c @capacity=3, @cnt=3>]
[:<, 4, true, #<Demo:0x034d567c @capacity=3, @cnt=3>]
[:<, 5, true, #<Demo:0x034d567c @capacity=3, @cnt=3>]
[:<=, -1, false, #<Demo:0x034d512c @capacity=3>]
[:<=, 0, false, #<Demo:0x034d512c @capacity=3, @cnt=1>]
[:<=, 1, false, #<Demo:0x034d512c @capacity=3, @cnt=2>]
[:<=, 2, false, #<Demo:0x034d512c @capacity=3, @cnt=3>]
[:<=, 3, true, #<Demo:0x034d512c @capacity=3, @cnt=3>]
[:<=, 4, true, #<Demo:0x034d512c @capacity=3, @cnt=3>]
[:<=, 5, true, #<Demo:0x034d512c @capacity=3, @cnt=3>]
[:>=, -1, true, #<Demo:0x034d4d44 @capacity=3>]
[:>=, 0, true, #<Demo:0x034d4d44 @capacity=3>]
[:>=, 1, true, #<Demo:0x034d4d44 @capacity=3, @cnt=1>]
[:>=, 2, true, #<Demo:0x034d4d44 @capacity=3, @cnt=2>]
[:>=, 3, true, #<Demo:0x034d4d44 @capacity=3, @cnt=3>]
[:>=, 4, false, #<Demo:0x034d4d44 @capacity=3, @cnt=3>]
[:>=, 5, false, #<Demo:0x034d4d44 @capacity=3, @cnt=3>]
[:>, -1, true, #<Demo:0x034d4998 @capacity=3>]
[:>, 0, true, #<Demo:0x034d4998 @capacity=3, @cnt=1>]
[:>, 1, true, #<Demo:0x034d4998 @capacity=3, @cnt=2>]
[:>, 2, true, #<Demo:0x034d4998 @capacity=3, @cnt=3>]
[:>, 3, false, #<Demo:0x034d4998 @capacity=3, @cnt=3>]
[:>, 4, false, #<Demo:0x034d4998 @capacity=3, @cnt=3>]
[:>, 5, false, #<Demo:0x034d4998 @capacity=3, @cnt=3>]
[:==, -1, false, #<Demo:0x034d4600 @capacity=3>]
[:==, 0, false, #<Demo:0x034d4600 @capacity=3, @cnt=1>]
[:==, 1, false, #<Demo:0x034d4600 @capacity=3, @cnt=2>]
[:==, 2, false, #<Demo:0x034d4600 @capacity=3, @cnt=3>]
[:==, 3, true, #<Demo:0x034d4600 @capacity=3, @cnt=3>]
[:==, 4, false, #<Demo:0x034d4600 @capacity=3, @cnt=3>]
[:==, 5, false, #<Demo:0x034d4600 @capacity=3, @cnt=3>]
[:!=, -1, true, #<Demo:0x034d4268 @capacity=3>]
[:!=, 0, true, #<Demo:0x034d4268 @capacity=3, @cnt=1>]
[:!=, 1, true, #<Demo:0x034d4268 @capacity=3, @cnt=2>]
[:!=, 2, true, #<Demo:0x034d4268 @capacity=3, @cnt=3>]
[:!=, 3, false, #<Demo:0x034d4268 @capacity=3, @cnt=3>]
[:!=, 4, true, #<Demo:0x034d4268 @capacity=3, @cnt=3>]
[:!=, 5, true, #<Demo:0x034d4268 @capacity=3, @cnt=3>]
[:<, -1, false, #<Demo:0x00007f64147c37e0 @capacity=6>]
[:<, 0, false, #<Demo:0x00007f64147c37e0 @capacity=6>]
[:<, 1, false, #<Demo:0x00007f64147c37e0 @capacity=6, @cnt=2>]
[:<, 2, false, #<Demo:0x00007f64147c37e0 @capacity=6, @cnt=3>]
[:<, 3, false, #<Demo:0x00007f64147c37e0 @capacity=6, @cnt=5>]
[:<, 4, true, #<Demo:0x00007f64147c37e0 @capacity=6, @cnt=6>]
[:<, 5, true, #<Demo:0x00007f64147c37e0 @capacity=6, @cnt=6>]
[:<=, -1, false, #<Demo:0x00007f64147c21d8 @capacity=6>]
[:<=, 0, false, #<Demo:0x00007f64147c21d8 @capacity=6, @cnt=2>]
[:<=, 1, false, #<Demo:0x00007f64147c21d8 @capacity=6, @cnt=3>]
[:<=, 2, false, #<Demo:0x00007f64147c21d8 @capacity=6, @cnt=5>]
[:<=, 3, true, #<Demo:0x00007f64147c21d8 @capacity=6, @cnt=6>]
[:<=, 4, true, #<Demo:0x00007f64147c21d8 @capacity=6, @cnt=6>]
[:<=, 5, true, #<Demo:0x00007f64147c21d8 @capacity=6, @cnt=6>]
[:>=, -1, true, #<Demo:0x00007f64147c0860 @capacity=6>]
[:>=, 0, true, #<Demo:0x00007f64147c0860 @capacity=6>]
[:>=, 1, true, #<Demo:0x00007f64147c0860 @capacity=6, @cnt=2>]
[:>=, 2, true, #<Demo:0x00007f64147c0860 @capacity=6, @cnt=3>]
[:>=, 3, true, #<Demo:0x00007f64147c0860 @capacity=6, @cnt=5>]
[:>=, 4, false, #<Demo:0x00007f64147c0860 @capacity=6, @cnt=6>]
[:>=, 5, false, #<Demo:0x00007f64147c0860 @capacity=6, @cnt=6>]
[:>, -1, true, #<Demo:0x00007f64147df260 @capacity=6>]
[:>, 0, true, #<Demo:0x00007f64147df260 @capacity=6, @cnt=2>]
[:>, 1, true, #<Demo:0x00007f64147df260 @capacity=6, @cnt=3>]
[:>, 2, true, #<Demo:0x00007f64147df260 @capacity=6, @cnt=5>]
[:>, 3, false, #<Demo:0x00007f64147df260 @capacity=6, @cnt=6>]
[:>, 4, false, #<Demo:0x00007f64147df260 @capacity=6, @cnt=6>]
[:>, 5, false, #<Demo:0x00007f64147df260 @capacity=6, @cnt=6>]
[:==, -1, false, #<Demo:0x00007f64147dd898 @capacity=6>]
[:==, 0, false, #<Demo:0x00007f64147dd898 @capacity=6, @cnt=2>]
[:==, 1, false, #<Demo:0x00007f64147dd898 @capacity=6, @cnt=3>]
[:==, 2, false, #<Demo:0x00007f64147dd898 @capacity=6, @cnt=5>]
[:==, 3, true, #<Demo:0x00007f64147dd898 @capacity=6, @cnt=6>]
[:==, 4, false, #<Demo:0x00007f64147dd898 @capacity=6, @cnt=6>]
[:==, 5, false, #<Demo:0x00007f64147dd898 @capacity=6, @cnt=6>]
[:!=, -1, true, #<Demo:0x00007f64147dbf20 @capacity=6>]
[:!=, 0, true, #<Demo:0x00007f64147dbf20 @capacity=6, @cnt=2>]
[:!=, 1, true, #<Demo:0x00007f64147dbf20 @capacity=6, @cnt=3>]
[:!=, 2, true, #<Demo:0x00007f64147dbf20 @capacity=6, @cnt=5>]
[:!=, 3, false, #<Demo:0x00007f64147dbf20 @capacity=6, @cnt=6>]
[:!=, 4, true, #<Demo:0x00007f64147dbf20 @capacity=6, @cnt=6>]
[:!=, 5, true, #<Demo:0x00007f64147dbf20 @capacity=6, @cnt=6>]

```





-- 
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/