# Swift's closure
# https://d...content-available-to-author-only...e.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
class String
class << self
def __unfoldl_rec__(b, &block)
return self.to_enum(:__unfoldl_rec__, b) unless block_given?
if (pair = yield b).nil?
''
else
a, b1 = pair
__unfoldl_rec__(b1, &block) + a
end
end
def __unfoldl_until__(b)
return self.to_enum(:__unfoldl_until__, b) unless block_given?
s = ''
until (pair = yield b).nil?
a, b = pair
s += a
end
s
end
def __unfoldl_loop__(b)
return self.to_enum(:__unfoldl_loop__, b) unless block_given?
loop.inject([b, '']) { |(b1, s), _|
if (pair = yield b1).nil?
break s
else
a, b2 = pair
[b2, a + s]
end
}
end
# alias unfoldl __unfoldl_rec__
alias unfoldl __unfoldl_until__
# alias unfoldl __unfoldl_loop__
end
end
DigitNames = {
0 => "Zero", 1 => "One", 2 => "Two", 3 => "Three", 4 => "Four",
5 => "Five", 6 => "Six", 7 => "Seven", 8 => "Eight", 9 => "Nine"
}
Numbers = [16, 58, 510]
puts '==== Internal enumerator ===='
strings = Numbers.map { |number|
String.unfoldl(number) { |num|
if num <= 0
nil
else
[DigitNames[num % 10], num / 10]
end
}
}
for s in strings
puts s
end
puts
puts '==== External enumerator (aka. Generator) ===='
strings = Numbers.map { |number|
for num in String.unfoldl(number)
if num <= 0
nil
else
[DigitNames[num % 10], num / 10]
end
end
}
for s in strings
puts s
end
IyBTd2lmdCdzIGNsb3N1cmUKIyAgIGh0dHBzOi8vZC4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uZS5jb20vbGlicmFyeS9pb3MvZG9jdW1lbnRhdGlvbi9Td2lmdC9Db25jZXB0dWFsL1N3aWZ0X1Byb2dyYW1taW5nX0xhbmd1YWdlL0Nsb3N1cmVzLmh0bWwKCgpjbGFzcyBTdHJpbmcKICAgIGNsYXNzIDw8IHNlbGYKICAgICAgICBkZWYgX191bmZvbGRsX3JlY19fKGIsICZibG9jaykKICAgICAgICAgICAgcmV0dXJuIHNlbGYudG9fZW51bSg6X191bmZvbGRsX3JlY19fLCBiKSB1bmxlc3MgYmxvY2tfZ2l2ZW4/CgogICAgICAgICAgICBpZiAocGFpciA9IHlpZWxkIGIpLm5pbD8KICAgICAgICAgICAgICAgICcnCiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIGEsIGIxID0gcGFpcgoKICAgICAgICAgICAgICAgIF9fdW5mb2xkbF9yZWNfXyhiMSwgJmJsb2NrKSArIGEKICAgICAgICAgICAgZW5kCiAgICAgICAgZW5kCgoKICAgICAgICBkZWYgX191bmZvbGRsX3VudGlsX18oYikKICAgICAgICAgICAgcmV0dXJuIHNlbGYudG9fZW51bSg6X191bmZvbGRsX3VudGlsX18sIGIpIHVubGVzcyBibG9ja19naXZlbj8KCiAgICAgICAgICAgIHMgID0gJycKICAgICAgICAgICAgdW50aWwgKHBhaXIgPSB5aWVsZCBiKS5uaWw/CiAgICAgICAgICAgICAgICBhLCBiID0gcGFpcgoKICAgICAgICAgICAgICAgIHMgKz0gYQogICAgICAgICAgICBlbmQKCiAgICAgICAgICAgIHMKICAgICAgICBlbmQKCgogICAgICAgIGRlZiBfX3VuZm9sZGxfbG9vcF9fKGIpCiAgICAgICAgICAgIHJldHVybiBzZWxmLnRvX2VudW0oOl9fdW5mb2xkbF9sb29wX18sIGIpIHVubGVzcyBibG9ja19naXZlbj8KCiAgICAgICAgICAgIGxvb3AuaW5qZWN0KFtiLCAnJ10pIHsgfChiMSwgcyksIF98CiAgICAgICAgICAgICAgICBpZiAocGFpciA9IHlpZWxkIGIxKS5uaWw/CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgcwogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIGEsIGIyID0gcGFpcgoKICAgICAgICAgICAgICAgICAgICBbYjIsIGEgKyBzXQogICAgICAgICAgICAgICAgZW5kCiAgICAgICAgICAgIH0KICAgICAgICBlbmQKCgogICAgICAgICMgYWxpYXMgdW5mb2xkbCBfX3VuZm9sZGxfcmVjX18KICAgICAgICAgIGFsaWFzIHVuZm9sZGwgX191bmZvbGRsX3VudGlsX18KICAgICAgICAjIGFsaWFzIHVuZm9sZGwgX191bmZvbGRsX2xvb3BfXwogICAgZW5kCmVuZAoKCgpEaWdpdE5hbWVzID0gewogICAgMCA9PiAiWmVybyIsIDEgPT4gIk9uZSIsIDIgPT4gIlR3byIsICAgMyA9PiAiVGhyZWUiLCA0ID0+ICJGb3VyIiwKICAgIDUgPT4gIkZpdmUiLCA2ID0+ICJTaXgiLCA3ID0+ICJTZXZlbiIsIDggPT4gIkVpZ2h0IiwgOSA9PiAiTmluZSIKfQpOdW1iZXJzID0gWzE2LCA1OCwgNTEwXQoKCnB1dHMgJz09PT0gSW50ZXJuYWwgZW51bWVyYXRvciA9PT09JwpzdHJpbmdzID0gTnVtYmVycy5tYXAgeyB8bnVtYmVyfAogICAgU3RyaW5nLnVuZm9sZGwobnVtYmVyKSB7IHxudW18CiAgICAgICAgaWYgbnVtIDw9IDAKICAgICAgICAgICAgbmlsCiAgICAgICAgZWxzZQogICAgICAgICAgICBbRGlnaXROYW1lc1tudW0gJSAxMF0sIG51bSAvIDEwXQogICAgICAgIGVuZAogICAgfQp9Cgpmb3IgcyBpbiBzdHJpbmdzCiAgICBwdXRzIHMKZW5kCgoKcHV0cwpwdXRzICc9PT09IEV4dGVybmFsIGVudW1lcmF0b3IgKGFrYS4gR2VuZXJhdG9yKSA9PT09JwpzdHJpbmdzID0gTnVtYmVycy5tYXAgeyB8bnVtYmVyfAogICAgZm9yIG51bSBpbiBTdHJpbmcudW5mb2xkbChudW1iZXIpCiAgICAgICAgaWYgbnVtIDw9IDAKICAgICAgICAgICAgbmlsCiAgICAgICAgZWxzZQogICAgICAgICAgICBbRGlnaXROYW1lc1tudW0gJSAxMF0sIG51bSAvIDEwXQogICAgICAgIGVuZAogICAgZW5kCn0KCmZvciBzIGluIHN0cmluZ3MKICAgIHB1dHMgcwplbmQ=