开发者

change the original variable from a ruby block? [duplicate]

开发者 https://www.devze.com 2023-01-07 21:31 出处:网络
This question already has answers here: 开发者_如何学GoClosed 10 years ago. Possible Duplicate: 'pass parameter by reference' in Ruby?
This question already has answers here: 开发者_如何学Go Closed 10 years ago.

Possible Duplicate:

'pass parameter by reference' in Ruby?

in this example:

def test
  verb = 'nothing'
  yield verb
  puts verb
end

test {|verb| verb = 'something'}

it will print "nothing".

is it possible to change it to "something"?

thanks


You have to remember, variables in Ruby are just references to objects. Each reference is independent of any other reference, though they may refer to the same object.

The other thing to remember is the the scope of a block is the scope it was defined in. So for your block, verb is not in scope (because it was defined outside of the method where verb lives).

Besides the eval-binding hack mentioned by stephenjudkins, there are two ways to do what you want. One is just to assign verb:

def test
  verb = 'nothing'
  verb = yield verb
  puts verb
end

This pretty directly does what you want and is really the best way to go about it.

The other way is to directly mutate the object that's passed in:

test {|verb| verb.replace 'something'}

I don't recommend this, though, because it actually changes the string itself instead of just assigning a new string to the variable. So other places where the same string object is referenced, it will contain the new text. This isn't a problem in your example, but it's a massive bug waiting to happen in any real program.


In your function, yield verb will return the result of evaluating the block. The verb variable in the block is not the same variable as in test; they're different variables in different scopes. In Ruby, an assignment is an expression, so evaluating your block results in 'something', but you don't do anything with the value returned from the yield.

If, as I suspect, you want to reassign verb in test based on the value of the block, you'll have to do that yourself; e.g. verb = yield verb. The assignment in the block, however, would still have no effect in test.


Use String#replace:

def test
  verb = 'nothing'
  yield verb
  puts verb
end

test {|verb| verb.replace('something')}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号