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>
I am interested in further suggestions
is my implementation close to that of File.open?
Regards, Daniel
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
=> #<Resource:0x40206fe0 @id=0>
irb(main):020:0> Q.get {|r| puts r.id}
1
=> nil
irb(main):021:0>
I am interested in further suggestions
is my implementation close to that of File.open?
You're missing the cleanup part when called with a block. The crucial bit is that the block form allows proper cleanup under all circumstances by using begin - ensure.
Kind regards
robert
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
=> #<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
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
=> #<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.
Timothy Hunter wrote:
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
=> #<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