Here is the sample code:
irb(main):001:0> def test
irb(main):002:1> begin
irb(main):003:2* a = 1
irb(main):004:2> b = 2
irb(main):005:2> b
irb(main):006:2> ensure
irb(main):007:2* a
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> test
=> 2
I am expecting that 1 should be returned by is 2.
I also write another code to verify:
irb(main):011:0> def test
irb(main):012:1> begin
irb(main):013:2* a = 1
irb(main):014:2> b = 2
irb(main):015:2> b
irb(main):016:2> ensure
irb(main):017:2* a
irb(main):018:2> puts "hello"
irb(main):019:2> end
irb(main):020:1> end
=> nil
irb(main):022:0> test
hello
=> 2
So it is obviously that all codes in ensure block have been run. But the
return value is always the last value before ensure block.
···
--
Posted via http://www.ruby-forum.com/.
That is the intended semantics. The ensure block doesn't generate a
return value for the method. It is intended to contain code that should
be executed if the method returns normally or if the method is rolled
up during exception processing.
Gary Wright
···
On Mar 6, 2008, at 10:46 AM, Oliver Peng wrote:
So it is obviously that all codes in ensure block have been run. But the
return value is always the last value before ensure block.
Here is the sample code:
irb(main):001:0> def test
irb(main):002:1> begin
irb(main):003:2* a = 1
irb(main):004:2> b = 2
irb(main):005:2> b
irb(main):006:2> ensure
irb(main):007:2* a
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> test
=> 2
I am expecting that 1 should be returned by is 2.
Why should it? If you think about it you will see that it's actually good the way it is. The result of evaluating code in /ensure/ cannot be returned under all circumstances (see Gary's reply). And for normal execution of a block of code you want the result of the code block to be returned - not the result of /ensure/. The code in /ensure/ is intended to do some cleanup that has to occur under all circumstances but not interfere with normal processing.
So it is obviously that all codes in ensure block have been run. But the
return value is always the last value before ensure block.
Yes, no problem here.
Cheers
robert
···
On 06.03.2008 16:46, Oliver Peng wrote:
Robert Klemme wrote:
irb(main):009:1> end
=> nil
irb(main):010:0> test
=> 2
I am expecting that 1 should be returned by is 2.
Why should it? If you think about it you will see that it's actually
good the way it is. The result of evaluating code in /ensure/ cannot be
returned under all circumstances (see Gary's reply). And for normal
execution of a block of code you want the result of the code block to be
returned - not the result of /ensure/. The code in /ensure/ is intended
to do some cleanup that has to occur under all circumstances but not
interfere with normal processing.
So it is obviously that all codes in ensure block have been run. But the
return value is always the last value before ensure block.
Yes, no problem here.
Cheers
robert
Ok. I see.
I am also curious what will happen if I change the return value in
ensure block. Here is my test code:
irb(main):003:0> def test
irb(main):004:1> begin
irb(main):005:2* a = 1
irb(main):006:2> b =2
irb(main):007:2> b
irb(main):008:2> ensure
irb(main):009:2* b += 3
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> test
=> 2
It looks that the result value has been saved to a temp place before
running ensure block. Is that correct?
I also use global variable to test.
irb(main):014:0> @@value = 0
=> 0
irb(main):015:0> def test1
irb(main):016:1> begin
irb(main):017:2* @@value = 3
irb(main):018:2> ensure
irb(main):019:2* @@value = 8
irb(main):020:2> end
irb(main):021:1> end
=> nil
irb(main):023:0> test1
=> 3
irb(main):024:0> @@value
=> 8
···
On 06.03.2008 16:46, Oliver Peng wrote:
--
Posted via http://www.ruby-forum.com/\.
Robert Klemme wrote:
>> irb(main):009:1> end
>> => nil
>> irb(main):010:0> test
>> => 2
>>
>> I am expecting that 1 should be returned by is 2.
>
> Why should it? If you think about it you will see that it's actually
> good the way it is. The result of evaluating code in /ensure/ cannot be
> returned under all circumstances (see Gary's reply). And for normal
> execution of a block of code you want the result of the code block to be
> returned - not the result of /ensure/. The code in /ensure/ is intended
> to do some cleanup that has to occur under all circumstances but not
> interfere with normal processing.
>
>> So it is obviously that all codes in ensure block have been run. But the
>> return value is always the last value before ensure block.
>
> Yes, no problem here.
>
> Cheers
>
> robert
Ok. I see.
I am also curious what will happen if I change the return value in
ensure block. Here is my test code:
irb(main):003:0> def test
irb(main):004:1> begin
irb(main):005:2* a = 1
irb(main):006:2> b =2
irb(main):007:2> b
irb(main):008:2> ensure
irb(main):009:2* b += 3
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> test
=> 2
It looks that the result value has been saved to a temp place before
running ensure block. Is that correct?
The return value is determined the very moment the block ends, which
means that the *reference* is saved (as always in Ruby). But since
you used Fixnums and simply reassigned to b ("b += 3") this won't be
visible. But
irb(main):001:0> def t
irb(main):002:1> s="foo"
irb(main):003:1> ensure
irb(main):004:1* s.replace "see?"
irb(main):005:1> end
=> nil
irb(main):006:0> t
=> "see?"
irb(main):007:0>
In other words, of course you can change the object before it is returned.
I also use global variable to test.
irb(main):014:0> @@value = 0
=> 0
irb(main):015:0> def test1
irb(main):016:1> begin
irb(main):017:2* @@value = 3
irb(main):018:2> ensure
irb(main):019:2* @@value = 8
irb(main):020:2> end
irb(main):021:1> end
=> nil
irb(main):023:0> test1
=> 3
irb(main):024:0> @@value
=> 8
Same story: you reassigned.
Cheers
robert
···
2008/3/6, Oliver Peng <oliver.peng@skywave.com>:
> On 06.03.2008 16:46, Oliver Peng wrote:
--
use.inject do |as, often| as.you_can - without end
Robert Klemme wrote:
> Why should it? If you think about it you will see that it's actually
> Yes, no problem here.
irb(main):012:0> test
=> 2
It looks that the result value has been saved to a temp place before
running ensure block. Is that correct?
The return value is determined the very moment the block ends, which
means that the *reference* is saved (as always in Ruby). But since
you used Fixnums and simply reassigned to b ("b += 3") this won't be
visible. But
irb(main):001:0> def t
irb(main):002:1> s="foo"
irb(main):003:1> ensure
irb(main):004:1* s.replace "see?"
irb(main):005:1> end
=> nil
irb(main):006:0> t
=> "see?"
irb(main):007:0>
In other words, of course you can change the object before it is
returned.
irb(main):021:1> end
=> nil
irb(main):023:0> test1
=> 3
irb(main):024:0> @@value
=> 8
Same story: you reassigned.
Cheers
robert
Ok I see. If I want to change the return value in ensure block, I need
to change the object itself in the last line before ensure, not just
reassign the varialbe. I also write another test code which can
demonstrate clearly:
irb(main):003:0> class A
irb(main):004:1> attr_accessor :value
irb(main):005:1> end
=> nil
irb(main):006:0> def test
irb(main):007:1> begin
irb(main):008:2* a = A.new
irb(main):009:2> a.value = 1
irb(main):010:2> a
irb(main):011:2> ensure
irb(main):012:2* a.value = 2
irb(main):013:2> end
irb(main):014:1> end
=> nil
irb(main):015:0> test
=> #<A:0xb7be48a0 @value=2>
I also did a test to try to do return in ensure block and it has higher
priority. Here is my test code:
irb(main):022:0> def test
irb(main):023:1> begin
irb(main):024:2* a = 1
irb(main):025:2> a
irb(main):026:2> ensure
irb(main):027:2* return 2
irb(main):028:2> end
irb(main):029:1> end
=> nil
irb(main):030:0> test
=> 2
Finally I think the best way is to avoid returning value in ensure block
and always put the return value in the last line of function or use
return directly.
Thanks for your replay.
···
2008/3/6, Oliver Peng <oliver.peng@skywave.com>:
--
Posted via http://www.ruby-forum.com/\.