K
keithrbennett
I've recently been writing custom Enumerable classes, and thought it would be a good idea to support Enumerators as well. Making an Enumerable Enumerator-enabled seems to be as simple as adding the following line to the beginning of each():
return to_enum unless block_given?
However, I realized that I might be introducing a risk of resource leaks bydoing so. For example, if my enumerable opens a file to read from, and I read a few but not all values from an enumerator it gives me, then the Enumerable's each() method that feeds Enumerator's next method never completes, and the file close there is never executed.
Should I *not* support enumerators if this is the case?
My current workaround is to define a new 'close' method on the Enumerator returned by super.to_enum (see to_enum() call at https://github.com/keithrbennett/trick_bag/blob/master/lib/trick_bag/enumerables/file_line_reader.rb for an example). I then call the 'close' method when I'm done calling the enumerator's 'next' method.
In that trick_bag gem I have a FilteredEnumerable that can decorate (specifically, filter) enumerators (at https://github.com/keithrbennett/tr.../trick_bag/enumerables/filtered_enumerable.rb). I'm thinkingof adding a close to that enumerator too that calls the wrapped enumerator's close method if it exists:
def close
wrapped_enumerator.close if wrapped_enumerator.respond_to?close)
end
It would be nice if Ruby's Enumerator class defined a no-op close method sothis wouldn't be necessary.
A problem with my approach is that I've overridden to_enum to take 1 param instead of 0 params. This could be a problem if someone assumes that can call to_enum on an instance of my enumerable.
Any insight as to the best way to handle this?
Thanks.
return to_enum unless block_given?
However, I realized that I might be introducing a risk of resource leaks bydoing so. For example, if my enumerable opens a file to read from, and I read a few but not all values from an enumerator it gives me, then the Enumerable's each() method that feeds Enumerator's next method never completes, and the file close there is never executed.
Should I *not* support enumerators if this is the case?
My current workaround is to define a new 'close' method on the Enumerator returned by super.to_enum (see to_enum() call at https://github.com/keithrbennett/trick_bag/blob/master/lib/trick_bag/enumerables/file_line_reader.rb for an example). I then call the 'close' method when I'm done calling the enumerator's 'next' method.
In that trick_bag gem I have a FilteredEnumerable that can decorate (specifically, filter) enumerators (at https://github.com/keithrbennett/tr.../trick_bag/enumerables/filtered_enumerable.rb). I'm thinkingof adding a close to that enumerator too that calls the wrapped enumerator's close method if it exists:
def close
wrapped_enumerator.close if wrapped_enumerator.respond_to?close)
end
It would be nice if Ruby's Enumerator class defined a no-op close method sothis wouldn't be necessary.
A problem with my approach is that I've overridden to_enum to take 1 param instead of 0 params. This could be a problem if someone assumes that can call to_enum on an instance of my enumerable.
Any insight as to the best way to handle this?
Thanks.