From: Timothy Hunter Date: 2006-07-31T05:19:14+09:00 Subject: Re: mimic File.open pattern Daniel Schierbeck wrote: > Sch�le Daniel wrote: >> Hello all, >> >> open is singleton method of File and can be used in two ways >> >> # 1 way >> f = File.open("data") >> f.readline until f.lineno == 10 >> puts f.readline >> f.close >> >> # 2 way >> File.open("data") do |f| >> f.readline until f.lineno == 10 >> puts f.readline >> end >> >> I am trying to mimic this with my own classes >> >> irb(main):001:0> class Resource >> irb(main):002:1> @@cnt=0 >> irb(main):003:1> def initialize >> irb(main):004:2> @id = @@cnt >> irb(main):005:2> @@cnt += 1 >> irb(main):006:2> end >> irb(main):007:1> def id;@id;end >> irb(main):008:1> end >> => nil >> irb(main):009:0> class Q >> irb(main):010:1> def Q.get &block >> irb(main):011:2> r = Resource.new >> irb(main):012:2> if Kernel::block_given? >> irb(main):013:3> block.call(r) >> irb(main):014:3> else >> irb(main):015:3* return r >> irb(main):016:3> end >> irb(main):017:2> end >> irb(main):018:1> end >> => nil >> irb(main):019:0> Q.get >> => # >> irb(main):020:0> Q.get {|r| puts r.id} >> 1 >> => nil >> irb(main):021:0> > > First off, you can make it more efficient if your use `yield' instead > of calling the block explicitly: > > class Q > def self.get > if block_given? > yield Resource.new > else > Resource.new > end > end > end > > The above is what I'd go with, but there a lots of ways to accomplish > what you want. Take this for example: > > class Q > def self.get > yield resource = Resource.new > rescue LocalJumpError > resource > end > end > > or even shorter (though it'll catch other exceptions as well, so you > have to be careful) > > class Q > def self.get > yield(resource = Resource.new) rescue resource > end > end > > > Cheers, > Daniel > There's no need to golf this. There's a well-known idiom for coding block-scoped resources. See the section entitled "Destroy this object when it goes out of scope" at http://wiki.rubygarden.org/Ruby/page/show/RubyIdioms. Here's the example from that page: def Resource.open( identifier ) # :yield: resource resource = Resource.new( identifier ) if block_given? begin yield resource ensure resource.close end else return resource end end The benefit of using the standard idiom is that any Ruby programmer that reads your code will instantly understand what it's doing. Coding it any other way will likely cause a bit of confusion. And, of course, if you don't use the idiom you might forget the "ensure" part.