Реализация Ленивого Перечислителя в Кристалле
В Ruby для создания собственного ленивого перечислителя можно использовать Enumerator
как это:
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"
Какой идиоматический способ Кристалла подражать такой вещи?
1 ответ
Решение
Немного словеснее... Посмотрите на 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"
(Не могу использовать enum
в качестве идентификатора, так как это ключевое слово в Crystal.)
Вы можете сделать это намного проще, если пожертвуете перемоткой:
s = ".a"
e = Iterator.of { s.tap { s = s.succ } }
Возможно, в будущем найдется способ сделать то же, что и в Ruby, но эта работа еще не завершена (я надеюсь, что она еще не заброшена, похоже, она застопорилась полгода назад). Посмотрите эту проблему и этот запрос на получение дополнительной информации.