A simple question regarding ruby method argument

Discussion in 'Ruby' started by Shin guey Wong, Mar 14, 2007.

  1. 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/.
     
    Shin guey Wong, Mar 14, 2007
    #1
    1. Advertising

  2. Shin guey Wong

    Tim Becker Guest

    > 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
     
    Tim Becker, Mar 14, 2007
    #2
    1. Advertising

  3. 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/.
     
    Shin guey Wong, Mar 14, 2007
    #3
  4. Shin guey Wong

    Tim Becker Guest

    > 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
     
    Tim Becker, Mar 14, 2007
    #4
  5. Hi --

    On 3/14/07, Shin guey Wong <> 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)
     
    David A. Black, Mar 14, 2007
    #5
  6. Shin guey Wong

    John Dearden Guest

    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/.
     
    John Dearden, Aug 24, 2007
    #6
  7. 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)
     
    David A. Black, Aug 24, 2007
    #7
  8. Shin guey Wong

    John Dearden Guest

    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/.
     
    John Dearden, Aug 25, 2007
    #8
  9. Shin guey Wong

    Guest

    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)
     
    , Aug 25, 2007
    #9
  10. On 8/24/07, 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.

    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/.
    >
    >
     
    Logan Capaldo, Aug 25, 2007
    #10
  11. Shin guey Wong

    John Dearden Guest

    Logan Capaldo wrote:
    > 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)


    Ah, well, now we're on to something! It looks a bit clunky to my
    untrained eye, but it will definitely do the job, and honors the Ruby
    'local variables are local' way.

    Thanks!
    John

    --
    Posted via http://www.ruby-forum.com/.
     
    John Dearden, Aug 25, 2007
    #11
  12. On 8/24/07, John Dearden <> wrote:
    > Logan Capaldo wrote:
    > > 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)

    >
    > Ah, well, now we're on to something! It looks a bit clunky to my
    > untrained eye, but it will definitely do the job, and honors the Ruby
    > 'local variables are local' way.
    >

    You're right it does look a little clunky, but I doubt your problem is
    so mundane in reality. (And I suspect ultimately there's a better
    solution than out / ref vars or multiple returns for your actual
    problem. But since we don't know what that is, we can't help :) )
    > Thanks!
    > John
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
     
    Logan Capaldo, Aug 25, 2007
    #12
  13. Shin guey Wong

    Guest

    Hi Tim - your example is great but I don't you phrased that right.

    You're saying:
    Ruby passes objects by reference

    I think it's:
    Ruby passes object references by copy

    Same as Java, like you said.

    --Dave


    On Aug 24, 2:15 pm, 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.
    >
    > Thanks in advance,
    > John
    > --
    > Posted viahttp://www.ruby-forum.com/.
     
    , Aug 25, 2007
    #13
  14. Shin guey Wong

    Guest

    Hi --

    On Sat, 25 Aug 2007, John Dearden wrote:

    > Logan Capaldo wrote:
    >> 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)

    >
    > Ah, well, now we're on to something! It looks a bit clunky to my
    > untrained eye, but it will definitely do the job, and honors the Ruby
    > 'local variables are local' way.


    Don't worry; Ruby won't let you dishonor that :)

    Keep in mind that most of the time, you'll probably be assigning the
    results to other variables. Using my earlier example:

    def change_me(a)
    a + 2
    end

    you'd then probably do something like:

    n = 2
    m = change_me(n) # as opposed to reassigning to n

    which looks a little less clunky and, in a real program, would
    probably make lots of sense. Both I and Logan (I surmise) provided you
    with examples that did the reassigning to the same variable, just to
    match what you were doing as closely as possible, but it's a general
    technique.

    Of course, you'll also see a lot of this:

    n = m.change_me

    depending on exactly what's going on.


    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)
     
    , Aug 25, 2007
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?ISO-8859-1?Q?Christian_M=F6rck?=

    Problem posting a method as an argument to an method..

    =?ISO-8859-1?Q?Christian_M=F6rck?=, Nov 20, 2003, in forum: C++
    Replies:
    4
    Views:
    305
    Christian M?rck
    Nov 21, 2003
  2. Bhushit Joshipura

    defaulting argument to previous argument

    Bhushit Joshipura, Dec 29, 2003, in forum: C++
    Replies:
    5
    Views:
    416
  3. Ben Kial
    Replies:
    1
    Views:
    660
    Eric Enright
    Nov 15, 2004
  4. S?ren Gammelmark
    Replies:
    1
    Views:
    1,893
    Eric Sosman
    Jan 7, 2005
  5. mike
    Replies:
    5
    Views:
    339
    Ben Pope
    Feb 22, 2006
Loading...

Share This Page