Seems like a cheap way to get upvotes.
Seems like a cheap way to get upvotes.
File.open("...") do |f|
firstline = f.readline
... stuff that might throw an exception ...
end
If the "stuff" throws an exception, the file gets closed automatically. And while File is a library class, it's getting no special favors here --- any pure ruby library can easily implement similar APIs, and ActiveRecord's connection pool, for example, actually does. File.open("...") do |f|
... stuff that might throw an exception ...
end
The syntax you see here is for passing a block to a method. In this case, you're passing a block to File.open, which opens the file, executes your block with it and then makes sure to close the file no matter what.In Python, you would do:
with open("x.txt") as f:
... stuff that might throw an exception ...
What this does is evaluate open("x.txt"), call the __enter__ method on the resulting value (called the context guard), assign the result of the __enter__ method to f, executes the body of the with statement and makes sure to call __exit__ method of the guard.The difference is that the syntax used in the Ruby example uses is not syntactic sugar for Dispose pattern, it's part of Ruby's syntax for working with blocks in general, whereas the syntax used in Python example is syntactic sugar meant for Dispose pattern (but can be used for other stuff too).
The argument for try...finally, using, lisp's (with-open-file...), etc. is that it makes it clear that there is 'invisible' code at the end of the block.
I suspect that is the reason for the 'scope' sugar in D. Its advantage is that it is more light-weight; its disadvantage that it does not stand out more. I guess it depends on what you think your audience can handle which is better for your case. I do not think there are many programmers that need java's very explicit try-finally because they cannot grasp e.g. what D provides, but I also have been surprised at times by the, let's say, intelligence, of programmers I met.
using(var resource = new Resource())
{
// potential code that throws exception
}http://download.java.net/jdk7/docs/technotes/guides/language...
The solution to this problem that makes sense to me is either conditions and restarts a la Common Lisp, or a type system that can handle multiple return values of different types in a sane way (e.g. return either a result or an error code and then pattern match against them) so that you don't always need to throw an exception in order to deal with an error.
with open("some.filename") as f:
...
f is an opened file which is automatically closed. This isn't strictly necessary in Python, since files are flushed and closed when reaped, including in case of exception, but it's useful. You can also do this with all of the threading primitives: with threading.Lock():
do_that_one_contentious_thing()
Useless syntactic sugar? Maybe. It's an explicit scope which makes certain guarantees, though, so it's not just fluff.What was his other example? DB connections? Well, in Python, the DB API requires that DB connections not easily leak, but if you're stuck with a crappy driver, you can still auto-close your connections:
with contextlib.closing(dbapi.Connection(...)) as handle:
cursor = handle.cursor()
...
So it's definitely possible.I think it's unfair of him to pick on Ruby and Python just because their syntax is more oriented towards assuming the garbage collector is non-sucky and exceptions aren't expensive.
Edit: Fixed formatting.