In Ruby to build a custom lazy enumerator, one can utilize Enumerator
like this:
enum = Enumerator.new do |e|
e << value = ".a"
loop { e << value = value.next }
end
enum.next # => ".a"
enum.next # => ".b"
enum.next # => ".c"
enum.rewind
enum.next # => ".a"
What's the Crystal's idiomatic way to imitate such a thing?
A bit wordier... Look at Iterator<T>
class DotChar
include Iterator(String)
@current : String = ""
def initialize
@start = ".a"
rewind
end
def next
@current.tap { @current = @current.succ }
end
def rewind
@current = @start
end
end
e = DotChar.new
p e.next # => ".a"
p e.next # => ".b"
p e.next # => ".c"
e.rewind
p e.next # => ".a"
(Can't use enum
as the identifier, as that's a keyword in Crystal.)
You can do it much simpler if you sacrifice rewind:
s = ".a"
e = Iterator.of { s.tap { s = s.succ } }
There may be in the future a way to do exactly as in Ruby, but it is a work in progress (that I hope wasn't abandoned yet, it seems to have stalled half a year ago). See this issue and this pull request for more info.