Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   A simple question regarding ruby method argument (http://www.velocityreviews.com/forums/t839039-a-simple-question-regarding-ruby-method-argument.html)

Shin guey Wong 03-14-2007 11:11 AM

A simple question regarding ruby method argument
 
Hi,

I am new to ruby and am learning it now. Can anyone point me how to pass
argument to method by reference? I mean that the methods/function able
to change the value of the argument. I am running windows using win32ole
and 1 of the method need to pass in an argument and the argument will
modify by the win32ole methods. But I don't know how to pass argument by
reference.

Thanks in advance.

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


Tim Becker 03-14-2007 11:25 AM

Re: A simple question regarding ruby method argument
 
> Can anyone point me how to pass
> argument to method by reference? I mean that the methods/function able
> to change the value of the argument.


Values are always passed by reference:

irb(main):011:0> class Test
irb(main):012:1> attr_accessor :a
irb(main):013:1> end

irb(main):014:0> def modify x
irb(main):015:1> x.a="hello"
irb(main):016:1> end

irb(main):017:0> t = Test.new
irb(main):018:0> t.a="there"

irb(main):019:0> modify t
irb(main):020:0> t.a
=> "hello"


what doesn't work is passing in a parameter `x`, assigning a new value
to x within a function and expecting that assignment to be
'transfered' outside the function scope:

def modify x
x=2 # this doesn't work, because it modifies the reference and not
# the referenced value
end

tmp=1
modify tmp # doesn't work as you'd like, tmp is still 1
puts tmp
=> 1


If you're familiar with Java, it's more or less the same behaviour.
-Tim


Shin guey Wong 03-14-2007 01:13 PM

Re: A simple question regarding ruby method argument
 
Tim Becker wrote:
> tmp=1
> modify tmp # doesn't work as you'd like, tmp is still 1
> puts tmp
> => 1
>


Hi Tim,

If I have a method which will need to modify the parameter passing to
it, how do I going to do that in ruby? In c we can pass in reference
using the & or c# using ref or out. But I am not sure Ruby have this
kind of keyword or not. The method I use is define by the com dll and I
calling it using win32ole.

Thanks.

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


Tim Becker 03-14-2007 01:38 PM

Re: A simple question regarding ruby method argument
 
> If I have a method which will need to modify the parameter passing to
> it, how do I going to do that in ruby?


Maybe you could post the source of the method so we can figure out how
to get around the problems you're experiencing.

> In c we can pass in reference


But if you pass in a pointer in C and assign a new value to the
pointer itself (instead of changing what is being pointed at) you
won't change the pointer variable outside of method scope either... In
c:

#include <stdio.h>

void test( int * x)
{
x=0; // modifies the reference, doesn't have the intended effect
}

void test2 (int * x)
{
*x=0; // modifies the referenced values, works.
}

int main (int argc, char * argv[]) {
int i=1;
printf("%d\n", i);
test (&i);
printf("%d\n", i);
test2 (&i);
printf("%d\n", i);
}

-Tim


David A. Black 03-14-2007 02:28 PM

Re: A simple question regarding ruby method argument
 
Hi --

On 3/14/07, Shin guey Wong <sgwong513@hotmail.com> wrote:
> Hi,
>
> I am new to ruby and am learning it now. Can anyone point me how to pass
> argument to method by reference? I mean that the methods/function able
> to change the value of the argument. I am running windows using win32ole
> and 1 of the method need to pass in an argument and the argument will
> modify by the win32ole methods. But I don't know how to pass argument by
> reference.


You're (almost) always passing references around anyway. Ruby doesn't
have references to references; all references are exactly one degree
away from the object to which they refer.

When you do this:

def amend(s)
s << " there."
end

str = "Hi"
amend(str)

you've changed the original string object:

puts str # Hi there.

because str holds a reference to that object, and s in the method is a
copy of str (i.e., a copy of the reference, not the string).


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)


John Dearden 08-24-2007 09:15 PM

Re: A simple question regarding ruby method argument
 
I am trying to write a method that changes the value of two arguments.
Stripped to the barest essentials, something like this:

def munge(a)
a = a + 1
end

zot = 3
print zot, "\n" # this should (and does) print '3'
munge(zot)
print zot, "\n" # this should print '4'. We wouldn't be here now if it
did!

Now, if I try the amend method given by David A. Black, it works as
expected. But it's passing a string object, not an integer.

Surely there is a way to give a method _something_ so that it can return
values to the caller. Of course, if I only ever had a single value to
return, I could make it the return value, but that's just begging the
question.

Thanks in advance,
John
--
Posted via http://www.ruby-forum.com/.


David A. Black 08-24-2007 09:39 PM

Re: A simple question regarding ruby method argument
 
Hi --

On Sat, 25 Aug 2007, John Dearden wrote:

> I am trying to write a method that changes the value of two arguments.
> Stripped to the barest essentials, something like this:
>
> def munge(a)
> a = a + 1
> end
>
> zot = 3
> print zot, "\n" # this should (and does) print '3'
> munge(zot)
> print zot, "\n" # this should print '4'. We wouldn't be here now if it
> did!
>
> Now, if I try the amend method given by David A. Black, it works as
> expected. But it's passing a string object, not an integer.
>
> Surely there is a way to give a method _something_ so that it can return
> values to the caller. Of course, if I only ever had a single value to
> return, I could make it the return value, but that's just begging the
> question.


Since integers are immutable (luckily!), and local variables are
local, you can't change an integer object via a reference copied to a
method. If it helps, I can assure you that you would *not* want this
to happen. It would be very weird if my local variables bindings were
at the mercy of methods that I called.

What you're really looking for is an object container, and local
variables don't really work that way. For container semantics you
really need to use containers. You could do something like:

def munge(a)
[*a][0] += 1
end

z = 3
y = *munge(z)

and so forth.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)


John Dearden 08-24-2007 11:25 PM

Re: A simple question regarding ruby method argument
 
David A. Black wrote:
...stuff deleted...
> Since integers are immutable (luckily!), and local variables are
> local, you can't change an integer object via a reference copied to a
> method. If it helps, I can assure you that you would *not* want this
> to happen. It would be very weird if my local variables bindings were
> at the mercy of methods that I called.
>
> What you're really looking for is an object container, and local
> variables don't really work that way. For container semantics you
> really need to use containers. You could do something like:


First, thanks for the quick answer. That was unexpected.

Unfortunately I can't say I understand the part of your response I
quoted above, other than that it says, "Nope, you can't do what you're
trying to do. Unless you're working with strings, which are somehow
different."

The "local variables _bindings_" bit implies to me this has something to
do with Ruby's underlying storage that I have not yet grasped. I'm
still thinking of a 'local variable' as really some chunk of memory, and
the way the bits are set in that memory mean something in the context of
my program. If I pass that location to a subprogram, and know that it's
going to put something else in it, that's good.

I can think of examples where I would like my subprogram to modify the
local variables of the calling code. For instance, I have two points,
and I want to calculate m and b for the formula of a line, as in y = m *
x + b. I would be inclined to write a subprogram calc_m_b(x1, y1, x2,
y2, var m, var b) (in Pascalese). I could do what amounts to the same
thing with two functions, one returning m and the other b, but that
seems sort of silly in this case. I could design an object that
represented a line in some fashion, and let it hold m and b, but that's
not always what you'd want, either.

Maybe I'm not thinking in terms of objects enough yet?

Thanks again,
John
--
Posted via http://www.ruby-forum.com/.


dblack@wobblini.net 08-24-2007 11:43 PM

Re: A simple question regarding ruby method argument
 
Hi --

On Sat, 25 Aug 2007, John Dearden wrote:

> David A. Black wrote:
> ...stuff deleted...
>> Since integers are immutable (luckily!), and local variables are
>> local, you can't change an integer object via a reference copied to a
>> method. If it helps, I can assure you that you would *not* want this
>> to happen. It would be very weird if my local variables bindings were
>> at the mercy of methods that I called.
>>
>> What you're really looking for is an object container, and local
>> variables don't really work that way. For container semantics you
>> really need to use containers. You could do something like:

>
> First, thanks for the quick answer. That was unexpected.
>
> Unfortunately I can't say I understand the part of your response I
> quoted above, other than that it says, "Nope, you can't do what you're
> trying to do. Unless you're working with strings, which are somehow
> different."
>
> The "local variables _bindings_" bit implies to me this has something to
> do with Ruby's underlying storage that I have not yet grasped. I'm
> still thinking of a 'local variable' as really some chunk of memory, and
> the way the bits are set in that memory mean something in the context of
> my program. If I pass that location to a subprogram, and know that it's
> going to put something else in it, that's good.
>
> I can think of examples where I would like my subprogram to modify the
> local variables of the calling code. For instance, I have two points,
> and I want to calculate m and b for the formula of a line, as in y = m *
> x + b. I would be inclined to write a subprogram calc_m_b(x1, y1, x2,
> y2, var m, var b) (in Pascalese). I could do what amounts to the same
> thing with two functions, one returning m and the other b, but that
> seems sort of silly in this case. I could design an object that
> represented a line in some fashion, and let it hold m and b, but that's
> not always what you'd want, either.
>
> Maybe I'm not thinking in terms of objects enough yet?


I agree my answer was sort of "You can't do the thing you just said
you can't do" :-) But that is sort of how it is. It's axiomatic in
Ruby that local variables are local. By "bindings" I mean:

def x(a)
a = 3 # a is bound to 3
end

a = 1 # *this* (different) a is bound to 1
x(a)
puts a # still 1

The call to x does not change the existing binding of a.

The only kind of change you can do in a situation like this is when a
variable is bound to a mutable object -- or, more accurately, a
variable contains a reference to a mutable object (since basically
Ruby variables traffic in references). That's where you get into
things like:

def add_to_array(a)
a.push("New element")
end

array = [1,2,3]
add_to_array(array)
p array # [1,2,3,"New element"]

If I use 'a' instead of 'array' for my array, the fact that
add_to_array also uses 'a' is just coincidence. There's no connection
between the two. It just happens that the identifier 'a' is used in
two local scopes to handle references to the same object.

The usual patterns you see in Ruby are either container-based,
object-based (where you have an object with an attribute; you pass the
object into the method and it does something to the attribute), or
assignment-based but in the same scope:


def change_me(a)
a + 2
end

a = 1
a = change_me(a) # a is now 3

I've pushed the assignment out of the method -- where it doesn't have
any effect except to set or change the method's local variables --
into the calling context. That way, I can do whatever I want with my
identifiers in each scope.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)


Logan Capaldo 08-25-2007 01:16 AM

Re: A simple question regarding ruby method argument
 
On 8/24/07, John Dearden <john.dearden@earthlink.net> wrote:
> I am trying to write a method that changes the value of two arguments.
> Stripped to the barest essentials, something like this:
>
> def munge(a)
> a = a + 1
> end
>
> zot = 3
> print zot, "\n" # this should (and does) print '3'
> munge(zot)
> print zot, "\n" # this should print '4'. We wouldn't be here now if it
> did!
>
> Now, if I try the amend method given by David A. Black, it works as
> expected. But it's passing a string object, not an integer.
>
> Surely there is a way to give a method _something_ so that it can return
> values to the caller. Of course, if I only ever had a single value to
> return, I could make it the return value, but that's just begging the
> question.

or you can return more than one value

def munge(a, b)
return a + 1, b - 2
end

q = 4
r = 9

q, r = munge(q, r)

>
> Thanks in advance,
> John
> --
> Posted via http://www.ruby-forum.com/.
>
>




All times are GMT. The time now is 08:59 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57