Timothy Hunter wrote:
> Daniel Schierbeck wrote:
>> Sche 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
>>> => #<Resource:0x40206fe0 @id=0>
>>> 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.

I don't think the original post mentioned that the resource needed to be 
closed :) I thought he wanted an easy way to either yield or return. But 
yes, for that wider problem, your code is superior. We were just 
answering different questions.


Cheers,
Daniel