Pass by reference in each loop

I have a list of variables that I need to pass through a modifying
function. Rather than specify for each one, I have them in an array,
and I loop through the array:

wml_needed = [@question, @answer_explanation]
wml_needed.each {|chunk| chunk = wml(chunk)}

The problem is that, unlike practically everything else in Ruby, each
loops don't pass by reference, so my assignments get lost.

Just to make sure, calling the function directly *does* work as
expected:

@question = wml(@question)

In PHP, I can add an ampersand (&) to the name (chunk, in this example)
to pass by reference instead of by copy; is there something similar in
Ruby, or should I be approaching this with a different method?

I realize that there are only two items in this example, but I'm
building for having many more.

···

--
Posted via http://www.ruby-forum.com/.

Xiong Chiamiov wrote:

I have a list of variables that I need to pass through a modifying
function. Rather than specify for each one, I have them in an array,
and I loop through the array:

wml_needed = [@question, @answer_explanation]
wml_needed.each {|chunk| chunk = wml(chunk)}

The problem is that, unlike practically everything else in Ruby, each
loops don't pass by reference, so my assignments get lost.

Just to make sure, calling the function directly *does* work as
expected:

@question = wml(@question)

In PHP, I can add an ampersand (&) to the name (chunk, in this example)
to pass by reference instead of by copy; is there something similar in
Ruby, or should I be approaching this with a different method?

I realize that there are only two items in this example, but I'm
building for having many more.

Check out Array#map!

···

--
RMagick: http://rmagick.rubyforge.org/

Xiong Chiamiov wrote:

The problem is that, unlike practically everything else in Ruby, each
loops don't pass by reference, so my assignments get lost.

You're confused. The variable chunk contains a reference to an object.
You are assigning a different reference to that variable, that's all.

For your problem, look into map (or map!)

···

--
Posted via http://www.ruby-forum.com/\.

Hi,

The problem is that, unlike practically everything else in Ruby, each
loops don't pass by reference, so my assignments get lost.

(...)

In PHP, I can add an ampersand (&) to the name (chunk, in this example)
to pass by reference instead of by copy; is there something similar in
Ruby, or should I be approaching this with a different method?

Ruby doesn't pass arguments by reference it passes them by value. What
is passed to functions/blocks is the reference value. When you're
assigning something to that variable, inside the block, you're getting a
new object assigned to that variable and that's why it won't work. When
you change an object that a variable holds reference to, you're changing
that object, each time you assign you're placing a reference to a new
object into that variable.

Creating an array let you pass the reference of that array, using that
reference value you can change it's content. The method map! changes the
object (! is a convention used in Ruby that indicates the method alters
the receiver) so it will work also. The last option, suggested by
Robert, assigns the result to the variable after method/block invocation
so it'll work also.

If you still have doubts about pass-by-reference vs pass-by-value see
how things work in C/C++ and in Java, the first is
pass-by-reference/pass-by-copy and the other pass-by-value.

Pedro Silva.

···

--
Posted via http://www.ruby-forum.com/\.

Anton Ivanov wrote:

Xiong Chiamiov wrote:

The problem is that, unlike practically everything else in Ruby, each
loops don't pass by reference, so my assignments get lost.

You're confused. The variable chunk contains a reference to an object.
You are assigning a different reference to that variable, that's all.

Ah, that makes sense. I was a bit puzzled by that behavior, since it
seemed like everything in Ruby passed by reference, but your explanation
helped me get it straight in my mind.

Tim Hunter wrote:

Check out Array#map!

That looks exactly right. Thanks!

···

--
Posted via http://www.ruby-forum.com/\.

Pedro Silva wrote:

Ruby doesn't pass arguments by reference it passes them by value. What
is passed to functions/blocks is the reference value.

Although that sounds exactly like passing by reference (doesn't it?),
I've come to understand today the nuance of how Ruby acts differently
(at least, I think).

In, say, C (ugh!), if I have some variable x and pass it to a function
by reference, it modifies the original x. If I pass by copy instead, it
copies it and modifies the copy, but not the original.
Ruby, however, (correct me if I'm wrong!) passes (essentially) by
reference. However, the difference is in how it treats the value
passed. When you modify it, instead of modifying the object that the
reference points to, you modify the reference itself to point to
something else.

This brings me back to my original question. While map! looked exactly
right, it modifies where the references in the array point to, rather
than modifying the values they pointed to, which means that my original
variables are not modified.

Robert Klemme wrote:

@question, @answer_explanation =
  [@question, @answer_explanation].map {|x| f(x)}

which *does* work, as it assigns the values back to the variables, but
it defeats the purpose of the thing.

Perhaps I should explain a little bit better why I'm going about this:

I'm building a lightweight parsing language. The function wml() parses
this. I have a lot of user input, some of which I want to parse, but
some I don't.

So then, I wanted to avoid writing:
@a = wml(@a)
@b = wml(@b)
@c = wml(@c)
...
because the list could potentially be quite long, and I'm the good kind
of lazy (the one referred to in the Camel book).

Robert's solution would allow me to only write the function name once,
but the variables I'd still have to type twice, and I really like DRY.

My first thought was to store a list of all those variables in an array
and loop through them, as it's then very easy to add an additional
variable. Perhaps I'm approaching this the complete wrong way, though?

···

--
Posted via http://www.ruby-forum.com/\.

Note that you can do

@question, @answer_explanation =
   [@question, @answer_explanation].map {|x| f(x)}

Btw, if this happens often, you probably rather want your variables in an array anyway.

Cheers

  robert

···

On 11.09.2008 03:24, Xiong Chiamiov wrote:

Anton Ivanov wrote:

Xiong Chiamiov wrote:

The problem is that, unlike practically everything else in Ruby, each
loops don't pass by reference, so my assignments get lost.

You're confused. The variable chunk contains a reference to an object. You are assigning a different reference to that variable, that's all.

Ah, that makes sense. I was a bit puzzled by that behavior, since it seemed like everything in Ruby passed by reference, but your explanation helped me get it straight in my mind.

Tim Hunter wrote:

Check out Array#map!

That looks exactly right. Thanks!

That's quite near to what I suggested: just drop all the @a, @b etc. and stuff everything in an array - or have multiple arrays, one per class of data (i.e. data which undergoes wml and data which does not). Anyway, chances are that you'll be able to find an elegant solution without needing to change the language.

Kind regards

  robert

···

On 11.09.2008 23:12, Xiong Chiamiov wrote:

Robert's solution would allow me to only write the function name once, but the variables I'd still have to type twice, and I really like DRY.

My first thought was to store a list of all those variables in an array and loop through them, as it's then very easy to add an additional variable. Perhaps I'm approaching this the complete wrong way, though?

Robert Klemme wrote:

Robert's solution would allow me to only write the function name once,
but the variables I'd still have to type twice, and I really like DRY.

My first thought was to store a list of all those variables in an array
and loop through them, as it's then very easy to add an additional
variable. Perhaps I'm approaching this the complete wrong way, though?

That's quite near to what I suggested: just drop all the @a, @b etc. and
stuff everything in an array - or have multiple arrays, one per class of
data (i.e. data which undergoes wml and data which does not). Anyway,
chances are that you'll be able to find an elegant solution without
needing to change the language.

Kind regards

  robert

I don't think I understood what you were suggesting the first time. If
I understand what you're suggesting, it is to have the values themselves
in the array, rather than variables pointing *to* those values, yes?

I need to know specifically which values are which, however, as they get
passed back into different parts of the output, so I'm thinking I'd have
to use a hash, something like

hash = {
'a' => 'this is actually input',
'b' => 'not hardcoded',
...
}

so that I could assign them appropriately afterwards:

hash.each {|key, value| key = value}

although, looking at that now, I don't think that it would work.

But as far as hash mapping (if that's what I have to do), I suppose I
could use one of the methods in this thread
(http://www.nabble.com/Iterating-through-a-hash-td19074540.html\), right?

I appreciate your help.

···

On 11.09.2008 23:12, Xiong Chiamiov wrote:

--
Posted via http://www.ruby-forum.com/\.

Xiong Chiamiov wrote:

I don't think I understood what you were suggesting the first time. If
I understand what you're suggesting, it is to have the values themselves
in the array, rather than variables pointing *to* those values, yes?

I need to know specifically which values are which, however, as they get
passed back into different parts of the output, so I'm thinking I'd have
to use a hash, something like

hash = {
'a' => 'this is actually input',
'b' => 'not hardcoded',
...
}

so that I could assign them appropriately afterwards:

hash.each {|key, value| key = value}

although, looking at that now, I don't think that it would work.

But as far as hash mapping (if that's what I have to do), I suppose I
could use one of the methods in this thread
(http://www.nabble.com/Iterating-through-a-hash-td19074540.html\), right?

I appreciate your help.

I think you're getting yourself more and more confused. Quit posting,
fire up irb and play around. What do you get when you do hash.each
{|key, value| key = value} ? Is there any difference between
[1,2,3].each {|x|} and a,b,c=1,2,3; [a,b,c].each {|x|}? etc.

···

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme wrote:

Robert's solution would allow me to only write the function name once,
but the variables I'd still have to type twice, and I really like DRY.

My first thought was to store a list of all those variables in an array
and loop through them, as it's then very easy to add an additional
variable. Perhaps I'm approaching this the complete wrong way, though?

That's quite near to what I suggested: just drop all the @a, @b etc. and
stuff everything in an array - or have multiple arrays, one per class of
data (i.e. data which undergoes wml and data which does not). Anyway,
chances are that you'll be able to find an elegant solution without
needing to change the language.

I don't think I understood what you were suggesting the first time. If
I understand what you're suggesting, it is to have the values themselves
in the array, rather than variables pointing *to* those values, yes?

What exactly do you mean by "variable pointing to those values"? This
wording does not really seem to make sense in Ruby. The value
(object) does not care how many references are around pointing to it.
With

@x = Object.new
@y = Object.new
@a = [@x, @y]

and

@a = [Object.new, Object.new]

there is no difference with regard to array contents. I suggest to
use the latter and drop the former *if* you have to treat them
uniformly more often than not.

I need to know specifically which values are which, however, as they get
passed back into different parts of the output, so I'm thinking I'd have
to use a hash, something like

hash = {
'a' => 'this is actually input',
'b' => 'not hardcoded',
...
}

so that I could assign them appropriately afterwards:

hash.each {|key, value| key = value}

although, looking at that now, I don't think that it would work.

It won't.

But as far as hash mapping (if that's what I have to do), I suppose I
could use one of the methods in this thread
(http://www.nabble.com/Iterating-through-a-hash-td19074540.html\), right?

Yep. Problem is, you present just a very tiny piece of your
application so it is extremely hard for use to suggest an appropriate
solution.

Cheers

robert

···

2008/9/12 Xiong Chiamiov <xiong.chiamiov+ruby_forum@gmail.com>:

On 11.09.2008 23:12, Xiong Chiamiov wrote:

--
use.inject do |as, often| as.you_can - without end

Anton Ivanov wrote:

I think you're getting yourself more and more confused. Quit posting,
fire up irb and play around. What do you get when you do hash.each
{|key, value| key = value} ? Is there any difference between
[1,2,3].each {|x|} and a,b,c=1,2,3; [a,b,c].each {|x|}? etc.

I think that the solution is the only part that confuses me now. I've
done quite a bit of playing around with irb, which is how I got to
understanding that I can't seem to do what I want (DRY) with the method
I was trying to use (variables in an array). What I'm trying to find
now is if there *is* a solution that will work for my particular
circumstances.

···

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme wrote:

That's quite near to what I suggested: just drop all the @a, @b etc. and
stuff everything in an array - or have multiple arrays, one per class of
data (i.e. data which undergoes wml and data which does not). Anyway,
chances are that you'll be able to find an elegant solution without
needing to change the language.

I don't think I understood what you were suggesting the first time. If
I understand what you're suggesting, it is to have the values themselves
in the array, rather than variables pointing *to* those values, yes?

What exactly do you mean by "variable pointing to those values"?

Well, I'm not quite sure how to explain it. I think you cleared up what
I was thinking right after this part, though:

Robert Klemme wrote:

The value
(object) does not care how many references are around pointing to it.
With

@x = Object.new
@y = Object.new
@a = [@x, @y]

and

@a = [Object.new, Object.new]

there is no difference with regard to array contents.

Yep. Problem is, you present just a very tiny piece of your
application so it is extremely hard for use to suggest an appropriate
solution.

Ah, I knew I had part of it online somewhere:
http://production.xyztextbooks.com/wml.php/generator . This is the PHP
version (before I converted it to Rails), so it hasn't had the benefit
of some bugfixes and such, but you can at least *see* what I'm talking
about.

This page (http://production.xyztextbooks.com/wml.php/generator/syntax\)
has some of the basic syntactical things for this. Essentially, there
is an application called Webwork that uses a special dialect of Perl
intermingled with Tex, and I'm created a front-end to problem-creation,
which normally involves writing code that most teachers are not
comfortable with (see http://webwork.maa.org/wiki/SampleProblem1\).

So then, it's just a simple form (using form_tag, I believe), and I grab
all of the request parameters at the top of the script. The question,
answer and answer_explanation all need to be run through a method that
parses the wml (as I'm calling it) into Perl/Tex code appropriate for
the problem, for instance, from ==3/5== to \(frac{3}{5}\).

As you can see, it's currently only those three fields that I need to
parse; I don't want to use extra resources running everything through
parsing. In the future, though, I see a larger number of fields that
need to be parsed, which is what I'm trying to write for.

Currently none of this is in any sort of model (since it's not going in
a database, I thought it shouldn't be), but I'm thinking that perhaps
that would be a better way of doing things, and may simplify this whole
thing. Unfortunately, I'm not familiar enough with models to know if
it's something I should spend my time figuring out; if it is, I'm glad
to struggle through getting it to work, but I have other things to fix
if that won't be worthwhile.

So, the short of it is, that site is what I'm doing, for the most part.

And apologies if I seem a little on edge; while I've found the ruby
community to be quite helpful, I miss my PHP manual, with all of its
user comments that are ever-so-helpful. The more popular a language,
the easier it is to find things on it, so a popular language can be
easier to learn than a less popular one, even if the less popular
actually has a more gentle learning curve.

···

2008/9/12 Xiong Chiamiov <xiong.chiamiov+ruby_forum@gmail.com>:

--
Posted via http://www.ruby-forum.com/\.

# As you can see, it's currently only those three fields that I need to
# parse; I don't want to use extra resources running everything through
# parsing. In the future, though, I see a larger number of fields that
# need to be parsed, which is what I'm trying to write for.

better to give us a sample php code

fr what i can guess and gather, i think you need a hash with vars as keys whose values you want to change anytime

eg

we create 3 vars @a, @b, @c

@a=nil
#=> nil
@b=2
#=> 2
@c="test"
#=> "test"

we want to save them and their original values to a hash (so we can call each by their var name, so to speak :slight_smile:

vars={@a=>@a,@b=>@b,@c=>@c}
#=> {nil=>nil, 2=>2, "test"=>"test"}

at this point, you should notice that ruby does not keep the variable name in the hash, but the original object it pointed.

so just in case we want the names preserved,
we keep/create and save copy of those names, like so

vars_name={@a=>"@a",@b=>"@b",@c=>"@c"}
#=> {nil=>"@a", 2=>"@b", "test"=>"@c"}

(there are other ways like ostructs, attributes, etc.. but this maybe crude as it gets :slight_smile:

now let's try clobbering.
let us "change" the value that var @a was referring to

vars[@a]="from nil to something"
#=> "from nil to something"

let's see.

vars
#=> {nil=>"from nil to something", 2=>2, "test"=>"test"}

ah, success.
let's try the other vars.

vars[@b]= vars[@b]*2
#=> 4
vars
#=> {nil=>"from nil to something", 2=>4, "test"=>"test"}

vars[@c]= vars[@c].sub "t","b"
#=> "best"
vars
#=> {nil=>"from nil to something", 2=>4, "test"=>"best"}

ok.
now let's print the var names together w their old and new values

vars_name.values.zip(vars.to_a){|pair| p pair}
["@a", [nil, "from nil to something"]]
["@b", [2, 4]]
["@c", ["test", "best"]]
#=> nil

is that ok?
apologies if this is not what you want.

kind regards -botp

···

From: Xiong Chiamiov [mailto:xiong.chiamiov+ruby_forum@gmail.com]

So, one way to do it would be this:

class WhateverYouNameIt
  NEEDS_PARSING = [
    :foo,
    :bar,
  ]

  def initialize
    @inputs = {}
  end

  # code that fetches input from somewhere

  def parse
    NEEDS_PARSING.each do |label|
      @inputs[label] = wml(@inputs[label])
    end
  end
end

But then again, whether this approach is better ultimately depends on
- as I said - whether you more often than not need to treat those
inputs uniformly. This I cannot know and in case you are not, then
I'd just plain write the statements in code with all variables, i.e.

@foo = wml(@foo)
@bar = wml(@bar)

even if it looks tedious. Verbosity can be better at times because it
makes things clearer.

Cheers

robert

···

2008/9/12 Xiong Chiamiov <xiong.chiamiov+ruby_forum@gmail.com>:

Robert Klemme wrote:

2008/9/12 Xiong Chiamiov <xiong.chiamiov+ruby_forum@gmail.com>:

That's quite near to what I suggested: just drop all the @a, @b etc. and
stuff everything in an array - or have multiple arrays, one per class of
data (i.e. data which undergoes wml and data which does not). Anyway,
chances are that you'll be able to find an elegant solution without
needing to change the language.

I don't think I understood what you were suggesting the first time. If
I understand what you're suggesting, it is to have the values themselves
in the array, rather than variables pointing *to* those values, yes?

What exactly do you mean by "variable pointing to those values"?

Well, I'm not quite sure how to explain it. I think you cleared up what
I was thinking right after this part, though:

Robert Klemme wrote:

The value
(object) does not care how many references are around pointing to it.
With

@x = Object.new
@y = Object.new
@a = [@x, @y]

and

@a = [Object.new, Object.new]

there is no difference with regard to array contents.

Yep. Problem is, you present just a very tiny piece of your
application so it is extremely hard for use to suggest an appropriate
solution.

Ah, I knew I had part of it online somewhere:
http://production.xyztextbooks.com/wml.php/generator . This is the PHP
version (before I converted it to Rails), so it hasn't had the benefit
of some bugfixes and such, but you can at least *see* what I'm talking
about.

This page (http://production.xyztextbooks.com/wml.php/generator/syntax\)
has some of the basic syntactical things for this. Essentially, there
is an application called Webwork that uses a special dialect of Perl
intermingled with Tex, and I'm created a front-end to problem-creation,
which normally involves writing code that most teachers are not
comfortable with (see http://webwork.maa.org/wiki/SampleProblem1\).

So then, it's just a simple form (using form_tag, I believe), and I grab
all of the request parameters at the top of the script. The question,
answer and answer_explanation all need to be run through a method that
parses the wml (as I'm calling it) into Perl/Tex code appropriate for
the problem, for instance, from ==3/5== to \(frac{3}{5}\).

As you can see, it's currently only those three fields that I need to
parse; I don't want to use extra resources running everything through
parsing. In the future, though, I see a larger number of fields that
need to be parsed, which is what I'm trying to write for.

--
use.inject do |as, often| as.you_can - without end

This may or may not help you understand the relationship between variables,
references, and objects in Ruby. I wrote it quite some time ago.

http://talklikeaduck.denhaven2.com/articles/2006/09/13/on-variables-values-and-objects

···

On Fri, Sep 12, 2008 at 4:15 AM, Xiong Chiamiov < xiong.chiamiov+ruby_forum@gmail.com <xiong.chiamiov%2Bruby_forum@gmail.com>>wrote:

Robert Klemme wrote:
> 2008/9/12 Xiong Chiamiov <xiong.chiamiov+ruby_forum@gmail.com<xiong.chiamiov%2Bruby_forum@gmail.com>
>:
>>> That's quite near to what I suggested: just drop all the @a, @b etc.
and
>>> stuff everything in an array - or have multiple arrays, one per class
of
>>> data (i.e. data which undergoes wml and data which does not). Anyway,
>>> chances are that you'll be able to find an elegant solution without
>>> needing to change the language.
>>
>> I don't think I understood what you were suggesting the first time. If
>> I understand what you're suggesting, it is to have the values themselves
>> in the array, rather than variables pointing *to* those values, yes?
>
> What exactly do you mean by "variable pointing to those values"?

Well, I'm not quite sure how to explain it.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Peña, Botp wrote:

fr what i can guess and gather, i think you need a hash with vars as
keys whose values you want to change anytime

As I thought more and more about this, I began to realize that I already
had such a thing created for me, since all of these variables I was
pulling directly out of request parameters.

So, before, I had something along these lines:
http://pastebin.com/f55d4b664

And now, I modify the values directly in the params hash, then pass them
along to the template at the end: http://pastebin.com/fa6863e

Peña, Botp wrote:

better to give us a sample php code

Once again, I was being silly and forgot that this project resides on
GitHub: GitHub - xiongchiamiov/webwork

Rick Denatale wrote:

This may or may not help you understand the relationship between
variables,
references, and objects in Ruby. I wrote it quite some time ago.

http://talklikeaduck.denhaven2.com/articles/2006/09/13/on-variables-values-and-objects

That article firmed up for me that Ruby treats variables the same way as
Python, at least in my limited experience with both.

The part that it made me realize, though was that the way Ruby is
structured allows you to put values in an array, then modify the
originals, and the array is changed:

irb(main):001:0> a = 1
=> 1
irb(main):002:0> b = 2
=> 2
irb(main):003:0> c = 3
=> 3
irb(main):004:0> arr = [a, b, c]
=> [1, 2, 3]
irb(main):005:0> a = 0
=> 0
irb(main):006:0> arr
=> [0, 2, 3]

But not what I was trying to do, which is to change the array, and have
the values propagate backwards:

irb(main):001:0> a = 1
=> 1
irb(main):002:0> b = 2
=> 2
irb(main):003:0> c = 3
=> 3
irb(main):004:0> arr = [a, b, c]
=> [1, 2, 3]
irb(main):005:0> arr[0] = 0
=> 0
irb(main):006:0> a
=> 1

···

--
Posted via http://www.ruby-forum.com/\.

I'm not sure if you were asking for help, but I wanted to show off.
Ruby doesn't work the way you describe, but it can fake it pretty well.

You're going to have to use something other than variables, like methods:

arr = [1,2,3]
def a
  arr[0]
end
def b
  arr[1]
end
def c
  arr[2]
end

That's a lot of repetition, though, so I'd do this instead:

arr = [1,2,3]
%w{a b c}.each_with_index do |name, index|
  define_method name do
    arr[index]
  end
end

Or, if you're only going to be manipulating it once, you could just unpack the
array into variables when you're done:

arr = [1,2,3]
arr[0] = 0
a,b,c = arr

Or you could bypass the whole issue and use a hash instead of an array, if
that fits what you're looking for.

One more solution: Make something that looks like an array, but isn't:

class FakeArray
  VARS = [:a, :b, :c]
  attr_accessor *VARS

  def index
    self.send VARS[index]
  end
  def = index, value
    self.send "#{VARS[index]}=", value
  end

  def what_you_wanted
    a = 1
    b = 2
    c = 3
    self[0] = 0
    puts "a is #{a}"
  end

  # And if you want it to be even more array-like:
  include Enumerable
  def each
    VARS.each do |var|
      yield(self.send var)
    end
  end

  def length
    VARS.length
  end
end

I'll leave it as an exercise to the reader to figure out how to separate the
pseudo-array from the class where a, b, and c are defined. This provides a
bit more flexibility, as you could then have more than one pseudo-array:

arr1 = self.pseudo_array(:a, :b, :c)
arr2 = self.pseudo_array(:c, :b, :a)

arr1[0] = 42 # or whatever

# This should be true, then:
arr1[0] == arr2[2] == self.a

There is one possibility I haven't covered, which is how to actually wrap a
variable in a reference. I haven't covered that mostly because it isn't
really helpful here -- no matter how magical I make my IntegerWrapper, it
will be completely discarded when you do:

arr[0] = 0

Because that "arr[0] =" is calling a method on the array itself, not doing
anything to the object stored inside it.

···

On Monday 15 September 2008 16:16:11 Xiong Chiamiov wrote:

But not what I was trying to do, which is to change the array, and have
the values propagate backwards:

irb(main):001:0> a = 1
=> 1
irb(main):002:0> b = 2
=> 2
irb(main):003:0> c = 3
=> 3
irb(main):004:0> arr = [a, b, c]
=> [1, 2, 3]
irb(main):005:0> arr[0] = 0
=> 0
irb(main):006:0> a
=> 1

I don't think anybody has mentioned String#replace yet. Given the
original code:

wml_needed = [@question, @answer_explanation]
wml_needed.each {|chunk| chunk = wml(chunk)}

and assuming that @question and @answer_explanation refer to String
objects, then it can be made to work as follows:

  wml_needed.each {|chunk| chunk.replace(wml(chunk)) }

Quick explanation:

* @question contains a reference (pointer) to a string, let's call it
str1
* @answer_explanation contains a reference to another string, str2
* wml_needed is a reference to an newly-created array which also
contains references to str1 and str2
* using <ref>.replace, str1 and str2 are modified *in place*. All the
existing references still point to the original strings, but those
strings have mutated.
* since @q/@a and wml_needed both point to the same places, str1 and
str2, both "see" the updated versions of str1 and str2

However I find this is rarely needed - and note that it doesn't work for
objects which cannot be mutated (e.g. numbers).

If you need to modify instance variables, and there are only two, then
using the KISS principle you can just write

  @question = wml(@question)
  @answer = wml(@answer)

Here, wml() presumably returns a new string in each case, and so
@question and @answer are updated to point to the new string; the old
ones will be garbage-collected at some point in the future, as long as
there are no other live references to them.

If that's what you're actually trying to do, but you want to apply the
DRY principle, then it *is* possible to read and write instance
variables in a loop:

  [:@question, :@answer].each do |iv|
    instance_variable_set(iv, wml(instance_variable_get(iv)))
  end

Or, if you class has accessor methods (question, question=, answer and
answer=) you can do

  ["question", "answer"].each do |iv|
    send("#{iv}=", wml(send(iv)))
  end

The latter example in particular is worth working through until you
understand how it works.

Of course, if your data naturally sits in an array, then you could just
keep a single instance variable which refers to the array, and don't
keep duplicate instance variables. Then you can just use map or map! to
update the array.

HTH,

Brian.

···

--
Posted via http://www.ruby-forum.com/\.