[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

pass by reference in each loop

Xiong Chiamiov

9/10/2008 11:54:00 PM

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-....

17 Answers

Tim Hunter

9/11/2008 12:04:00 AM

0

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.ruby...

Anton Ivanov

9/11/2008 12:10:00 AM

0

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-....

Xiong Chiamiov

9/11/2008 1:24:00 AM

0

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-....

Robert Klemme

9/11/2008 6:37:00 AM

0

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!

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

Pedro Silva

9/11/2008 7:58:00 AM

0

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-....

Xiong Chiamiov

9/11/2008 9:13:00 PM

0

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-....

Robert Klemme

9/11/2008 9:45:00 PM

0

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?

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

Xiong Chiamiov

9/11/2008 10:08:00 PM

0

Robert Klemme wrote:
> 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?
>
> 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-td190...), right?

I appreciate your help.
--
Posted via http://www.ruby-....

Anton Ivanov

9/12/2008 12:19:00 AM

0

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-td190...), 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-....

Xiong Chiamiov

9/12/2008 12:32:00 AM

0

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-....