Skip to content

Instantly share code, notes, and snippets.

@okuramasafumi
Created March 22, 2022 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save okuramasafumi/c8c07f8dc5bf46795369044c3114539f to your computer and use it in GitHub Desktop.
Save okuramasafumi/c8c07f8dc5bf46795369044c3114539f to your computer and use it in GitHub Desktop.
EachWithEffect module for Ruby
module EachWithEffect
DEFAULT = Object.new.freeze
def each_with_effect(effect_handlers = {}, &block)
effect = catch(:effect) do
block.call(self.peek)
end
if effect
handler = effect_handlers.find{ |k, v| k === effect }&.last || effect_handlers.fetch(DEFAULT)
alternative = handler.call(effect) if handler
block.call(alternative) if alternative
end
begin
self.next
each_with_effect(effect_handlers, &block)
rescue StopIteration
# Do nothing
end
end
end
class Enumerator
include EachWithEffect
end
class Array
def each_with_effect(effect_handlers = {}, &block)
to_enum.each_with_effect(effect_handlers, &block)
end
end
[1, '2', 3, [4, 5]].each_with_effect(
String => ->(s) { s.to_i },
Array => ->(a) { a.sum },
EachWithEffect::DEFAULT => ->(o) { 42 }
) do |i|
throw(:effect, i) unless i.is_a?(Integer)
p i
nil
end
# => 1, 2, 3, 9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment