4 ms·
Surely ruby's blocks are much better here. For one they're a much more general construct than with, and second exception handling is done with normal language c
by RX14 9y ago
Surely ruby's blocks are much better here. For one they're a much more general construct than with, and second exception handling is done with normal language constructs like rescue and ensure. Implementing one is simple and obvious and is nicely contained in a single method.
For example
File.open(args) do |file|
# use file
end
And the implementation is simply
def self.open(*args)
file = File.new(*args)
begin
yield file
ensure
file.close
end
end
- int_19h 9y agoRuby does this at the cost of having non-local returns from those blocks, which complicates semantics quite a bit (since now you need to distinguish closures that capture "return" and other control transfer from those that don't, and you need to handle the scenario where a control transfer happens when the target is already gone).
- lstyls 9y agoI know Python far better than Ruby, but it looks like the semantics are equivalent, it's just that Ruby's standard `open` implementation includes the cleanup rather than leaving it up to the caller as in Python.
- masklinn 9y agoOne difference is that Ruby does not need a special language construct/protocol to do so. An other is that Python's "context managers" are reified which means you can pass them around until you ultimately use them. It's a tradeoff.
- asdfaoeu 9y agoYou can do basically the same thing in python @contextlib.contextmanager def open(*args) # file open try: yield file finally: file.close() with open(args) as file: # use file
- RX14 9y agoThat's pretty cool! But as nice as it is, to me it's just syntax sugar over the wrong abstraction instead of something beautiful in it's own right.
- masklinn 9y agoOn the other hand, it means any helper/builder has to handle this pattern on its own rather than be able to return a file object which can be "context managed" by a caller, which Python allows.