Enumerable works, Iterator doesn't, in 1.1.1

I was running old Rosetta Code examples with 1.1.1 and found this new error.

This code worked, at least upto 0.36.1, and compiles/run with 1.1.1.

struct PalindromicGapfuls
  include Enumerable(UInt64)

  @nn : Int32

  def initialize(@digit : Int32)
    @nn = @digit * 11                   # digit gapful divisor: 11, 22,...88, 99
  end

  def each
    (2..).each do |power|
      base    = 10_u64 ** (power >> 1)  # value of middle digit position: 10..
      this_lo = base * @digit           # starting half for this digit: 10.. to  90.. 
      next_lo = base * (@digit + 1)     # starting half for next digit: 20.. to 100..
      this_lo.step(to: next_lo - 1, by: 10) do |front_half|   # d_10; d_20; d_30; ...
        if power.odd?                   # for even number of total digits: ab..ba
          front_half.upto(front_half + 9) do |upper_half|     # d_n0 to d_n9
            palindrome_half = upper_half.to_s
            palindrome = (palindrome_half + palindrome_half.reverse).to_u64
            yield palindrome if palindrome % @nn == 0
          end
        else                            # for odd number of total digits: ab..m..ba
          palindrome_half = (front_half // 10).to_s           # d_n
          palindrome = (palindrome_half + "0" + palindrome_half.reverse).to_u64
          # increase palindrome middle digit from ---0--- to ---9---
          10.times do
            yield palindrome if palindrome % @nn == 0
            palindrome += base          # increase middle digit value
          end
        end
      end
    end
  end
end

count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }

This code worked, at least upto 0.36.1, but won’t compile with 1.1.1.

struct PalindromicGapfuls
  include Iterator(UInt64)

  @nn : Int32

  def initialize(@digit : Int32)
    @nn = @digit * 11                   # digit gapful divisor: 11, 22,...88, 99
  end

  def each
    (2..).each do |power|
      base    = 10_u64 ** (power >> 1)  # value of middle digit position: 10..
      this_lo = base * @digit           # starting half for this digit: 10.. to  90.. 
      next_lo = base * (@digit + 1)     # starting half for next digit: 20.. to 100..
      this_lo.step(to: next_lo - 1, by: 10) do |front_half|   # d_10; d_20; d_30; ...
        if power.odd?                   # for even number of total digits: ab..ba
          front_half.upto(front_half + 9) do |upper_half|     # d_n0 to d_n9
            palindrome_half = upper_half.to_s
            palindrome = (palindrome_half + palindrome_half.reverse).to_u64
            yield palindrome if palindrome % @nn == 0
          end
        else                            # for odd number of total digits: ab..m..ba
          palindrome_half = (front_half // 10).to_s           # d_n
          palindrome = (palindrome_half + "0" + palindrome_half.reverse).to_u64
          # increase palindrome middle digit from ---0--- to ---9---
          10.times do
            yield palindrome if palindrome % @nn == 0
            palindrome += base          # increase middle digit value
          end
        end
      end
    end
  end
end

count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).skip(count-keep)}" }

The error message is:

➜  rosettacode time crystal run palclass2.cr --release
Showing last frame. Use --error-trace for full trace.

In palclass2.cr:1:1

 1 | struct PalindromicGapfuls
     ^
Error: abstract `def Iterator(T)#next()` must be implemented by PalindromicGapfuls

The Docs for 1.1.1 show Iterator still have next and skip methods.

https://crystal-lang.org/api/1.1.1/Iterator.html

1 Like

This code worked, at least upto 0.36.1, but won’t compile with 1.1.1.

It didn’t compile with 0.36.1: Carcin

2 Likes

From the Iterator docs:

To implement an Iterator you need to define a #next method that must return the next element in the sequence or Iterator::Stop::INSTANCE, which signals the end of the sequence (you can invoke #stop inside an iterator as a shortcut).

i.e. Iterator#next is abstract: source

1 Like