By value or by reference?

By value or by reference?

Postby thomthom » Thu Feb 25, 2010 7:23 pm

When passing arguments from a method to another in Ruby, is that by value or by reference?
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: By value or by reference?

Postby Chris Fullmer » Thu Feb 25, 2010 7:31 pm

I had thought by reference always, unless its a fix_num, which is always a unique value, never a reference.

I juste tested by displaying the object id of a variable passed between different methods, and it keeps the same object id. So it sounds like it passes a reference.

def m2(a)
puts a.id
end

def m1
a = "hi"
puts a.id
ms(a)
end


That seems to demonstrate it.
0
Lately you've been tan, suspicious for the winter.
All my Plugins I've written
User avatar
Chris Fullmer 
SketchUp Team
SketchUp Team
 

Re: By value or by reference?

Postby jessejames » Thu Feb 25, 2010 9:24 pm

thomthom wrote:When passing arguments from a method to another in Ruby, is that by value or by reference?


Oh Lord, this very same question caused a major flame war to arrupt on c.l.python the other day, are you sure you want to ask this question?!? ;)
0
Always sleep with a loaded gun under your pillow!

jessejames 
 

Re: By value or by reference?

Postby Chris Fullmer » Thu Feb 25, 2010 9:38 pm

For the most part, we manage to avoid programming flame wars around here ;)
0
Lately you've been tan, suspicious for the winter.
All my Plugins I've written
User avatar
Chris Fullmer 
SketchUp Team
SketchUp Team
 

Re: By value or by reference?

Postby thomthom » Thu Feb 25, 2010 9:40 pm

what's there to flame about such a question? :?: people these days :roll:
yes - I'm sure I want to ask this - I'm curious.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: By value or by reference?

Postby Dan Rathbun » Sat Mar 06, 2010 5:49 am

Chris Fullmer wrote:I just tested by displaying the object id of a variable passed between different methods, and it keeps the same object id. So it sounds like it passes a reference.
Code: Select all
def m2(a)
  puts a.id
end

def m1
  a = "hi"
  puts a.id
  m2(a)
end
Correction (line 8): "m2(a)" was "ms(a)"

What I think ya'll are misunderstanding (and contrary to what most programming tutorials say,) about Ruby, is that Ruby DOES NOT really have TRUE VARIABLES.

'True variables', I mean in the sense that other languages such as the old BASIC or Pascal had variables, that were declared to 'BE' a certain datatype (int, real, string, etc.) AND kept a table in memory of those (variable) identifiers along with the current VALUE that was 'HELD' by them.

Ruby doesn't do this. EVERYTHING in Ruby is an OBJECT, including objects of the BASE classes (ie: Integer, Float, String, etc.) So when you code:
aVar = 8
in Ruby, you are NOT assigning the integer value 8 to a variable identifier, ... you are instead creating a reference, with the name aVar that POINTS at the first class object 8. The object 8 is an instance of class Integer, and so inherits methods from it's class, and superclasses, ie:
8.id
>> an id number
aVar.id
>> the same id number since it points at object 8
bVar = aVar
bVar.id
>> the same id number since it points at object 8

And as Chris said, Fixnum is special in that there can be ONLY 1 object for each ordinal in the Fixnum set.

The same is not true for other more complex types, such as Array, String, etc.
The best illustration of "how thinking" of Ruby references as variables (like in other languages,) can lead you to 'hair-pulling' frustration, was given in the forum over at Google Groups. (I answered and solved the poster's problem, but refered in my answer, to his 'reference' as 'an alias'; perhaps not so good as alias is a special kind of reference in Ruby for methods and don't work for "variables".)
Any how.. read that post, and examine flesk's code, and the solution TIG and I gave him (TIG and I are about 5/6 hours apart and posted about the same time, I think.)
Google Groups (Sketchup ruby API): Variable value error

So how would you 'pass by value'? (In the sense that you would in Pascal. You should have an idea, after reading that post.)
Let's modify Chris' code a bit:
Code: Select all
def m2(a)
  puts 'a in m2 has id: '+a.id.to_s
end

def m1
  a = "hi"
  puts 'a in m1 has id: '+a.id.to_s
  m2(a.dup)
end
Or if you wish to paste into the console, then (1 line at a time):
def m2(a); puts 'a in m2 has id: '+a.id.to_s; end
def m1; a = "hi"; puts 'a in m1 has id: '+a.id.to_s; m2(a.dup); end
and then type: m1
You'll see the id numbers differ.
NOTE: If you think this will save time or memory, it won't. Ruby will create an anonymous reference to the duplicated object, so there is still a 'reference assignment' behind the scenes. In fact if you look up at the modified code, at the 2 puts statements, the String arguments 'a in m1 has id: ' are also transparently assigned an anonymous reference, so I might just as well have stored the string in a named reference of my own, so both methods could use the same String object, but change the method name. Of course it's not necessary, as these objects will not 'live' long.
0
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: By value or by reference?

    Postby thomthom » Sat Mar 06, 2010 11:54 am

    Why do these two things differ: I pass a string to a method and modify the string:

    def m3(a); a += 'bar'; end

    > x = 'foo'
    foo
    > m3(x)
    foobar
    > x
    foo


    ...and the string outside the method is not changed.


    But use a Point3d:

    def m4(p); p.x = 99; end

    > n = Geom::Point3d.new(1,2,3)
    Point3d(1, 2, 3)
    > m4(n)
    99
    > n
    Point3d(99, 2, 3)


    And now it does change...

    When I pass Point3d objects to methods that modify the passed argument, I use p2 = p1.clone - but is this the best way to do get a local copy to work on?
    0
    Thomas Thomassen — SketchUp Monkey & Coding addict
    List of my plugins and link to the CookieWare fund
    User avatar
    thomthom 
    PluginStore Author
    PluginStore Author
     

    Re: By value or by reference?

    Postby Dan Rathbun » Sat Mar 06, 2010 12:37 pm

    thomthom wrote:Why do these two things differ: I pass a string to a method and modify the string:
    def m3(a); a += 'bar'; end
    (from the Ruby 'Pick-Axe' book):
    str + aString -> aNewString
    + Concatenation---Returns a *new* String containing aString concatenated to str.
    thomthom wrote:> x = 'foo'
    foo
    > m3(x)
    foobar
    > x
    foo

    ...and the string outside the method is not changed.

    Because 'foobar' is the *new* string object that was transparently constructed with String.new by Ruby.
    0
      I'm not here much anymore. But a PM will fire email notifications.
      User avatar
      Dan Rathbun 
      PluginStore Author
      PluginStore Author
       

      Re: By value or by reference?

      Postby thomthom » Sat Mar 06, 2010 1:01 pm

      Ok, but what about this one?

      > x = 'foo'
      foo
      > def m3(a); a = 'bar'; end
      nil
      > m3(x)
      bar
      > x
      foo


      :?:
      0
      Thomas Thomassen — SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund
      User avatar
      thomthom 
      PluginStore Author
      PluginStore Author
       

      Re: (Quick Note) String +=

      Postby Dan Rathbun » Sun Mar 07, 2010 12:12 am

      thomthom wrote:a += 'bar'

      Just a quick note about += for String objects.

      (We also discussed this in another thread.) EDIT ( :? got confused for a min; removed previous statement.)
      My advice is, for less confusion, use the proper String append operator: (It's the same work for typing!)
      a << 'bar'

      ADD: IMHO, the interpreter should raise a SyntaxError when it sees += for Strings. I wonder if a Warning is output?
      UPDATE: No, I tested += with $VERBOSE set to true, and no warning is output.
      0
        I'm not here much anymore. But a PM will fire email notifications.
        User avatar
        Dan Rathbun 
        PluginStore Author
        PluginStore Author
         

        Re: By value or by reference?

        Postby Dan Rathbun » Mon Mar 08, 2010 12:38 pm

        thomthom wrote:Ok, but what about this one?
        > x = 'foo'
        foo
        > def m3(a); a = 'bar'; end
        nil
        > m3(x)
        bar
        > x
        foo

        ..the above, is the same as:
        thomthom wrote:def m3(a); a += 'bar'; end

        > x = 'foo'
        foo
        > m3(x)
        foobar
        > x
        foo
        .. with respect to that:

        (1) the reference a, is at method start, pointing at the same string object 'foo' that the reference x is pointing at; ..and

        (2) then the expression on the right of the '=', in both cases, results in the creation of a *new* string object by Ruby.
        ..(a) In case 1, Ruby calls String.new('bar') (we'll call it: newbarstr.)
        ..(b) In case 2, Ruby first expands a += 'bar', into a = a + 'bar', then (as in case 1,) evaluates the right-hand expression, transparently passing literal string args to String.new, keeping track of the anonymous pointers to the new string objects. In this example there is only one (we'll call it newbarstr.) Then, it calls a.+(newbarstr) which is the string concatenation method, that returns yet another *new* string object created by Ruby (we'll call it foobarstr, but remember Ruby uses temporary numerical identifiers.) So at this point the right-hand expression is now done and set to temp string object foobarstr.

        (3) NOW.. both cases make a REFERENCE assignment, which assigns the reference a to point at the new String objects created from their evaluations.

        (4) Lacking any specific return expression, the method returns the last result, which is the value of the object that a was made to point at, which is NOT the object 'foo'.

        (5) Since the method call was made "stand-alone" and it's result not referenced, when the method exits, a will disposed of by Garbage Collection, along with any temporary objects Ruby used within the method.

        (6) .. all that's left, is reference x pointing at poor 'lil string object 'foo'.

        += vs. <<
        Looking back at (2)(b) above, and realizing all the work that is going on, and string objects being created, just to glue two substrings together.. we should all want to use << (the String append method,) instead.
        The main reason is, that it only creates one temporary string, IF the argument is a literal; otherwise NO temporary string, IF the argument is a reference to an existing string object.
        String.<< instead directly modifies the receiver string object by appending the string argument object onto it.


        Bottom line: Free Your Ruby Mind !! :idea:
        Throw away the word 'variable' and think 'reference'.
        $reference, global_reference, local_reference, instance_reference, @reference, class_reference, @@reference, module_reference ... reference, Reference, REFERENCE ! :sketchstatic:
        0
          I'm not here much anymore. But a PM will fire email notifications.
          User avatar
          Dan Rathbun 
          PluginStore Author
          PluginStore Author
           

          Re: By value or by reference?

          Postby Dan Rathbun » Mon Mar 08, 2010 12:57 pm

          thomthom wrote:Why do[es] ... Point3d [differ?]

          def m4(p); p.x = 99; end

          > n = Geom::Point3d.new(1,2,3)
          Point3d(1, 2, 3)
          > m4(n)
          99
          > n
          Point3d(99, 2, 3)

          And now it does change...

          Apples and Oranges.

          In this case, your calling a 'method operator' ie: Geom::Point3d.x= that happens to have a '=' character in the method name. It's not the same as the Ruby hard-coded = operator.

          Your getting confused because the interpreter allows you to insert a space into the method call.

          Also.. Geom::Point3d.x= is more similar to String.<<, in that the method doesn't replace an entire object, it only modifies part of the object.
          Specifically, Geom::Point3d.x= is an attribute setter method, involving Numerics, so no temporary Integer, and p is still pointing at the same object n is, so naturally, yes the common object gets modified.

          Since Geom::Point3d has no dup method, you'll have to use clone to create a copy.
          0
            I'm not here much anymore. But a PM will fire email notifications.
            User avatar
            Dan Rathbun 
            PluginStore Author
            PluginStore Author
             

            Re: By value or by reference?

            Postby tbd » Mon Mar 08, 2010 1:05 pm

            see also The Ruby programming language By David Flanagan, Yukihiro Matsumoto
            0
            Last edited by tbd on Mon Mar 08, 2010 1:07 pm, edited 1 time in total.
            SketchUp Ruby Consultant | Podium 1.x developer
            http://plugins.ro
            User avatar
            tbd 
             

            Re: By value or by reference?

            Postby thomthom » Mon Mar 08, 2010 1:05 pm

            Dan Rathbun wrote:In this case, your calling a 'method operator' ie: Geom::Point3d.x= that happens to have a '=' character in the method name. It's not the same as the Ruby hard-coded = operator.

            Your getting confused because the interpreter allows you to insert a space into the method call.


            Ahah! This is the core of my confusion indeed!

            .x= (which can be written .x =) is really just a Ruby naming conversion for .set_x.


            Thanks for this explanation Dan. Appreciate it.


            So using p2 = p1.clone is the proper way to get a copy of a point then?
            0
            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund
            User avatar
            thomthom 
            PluginStore Author
            PluginStore Author
             

            Re: By value or by reference?

            Postby thomthom » Mon Mar 08, 2010 1:14 pm

            TBD wrote:see also The Ruby programming language By David Flanagan, Yukihiro Matsumoto


            Interesting link. I think I need to read further into that book.
            Did remind me of another thing about Ruby - true/false, why they don't equal to 1 and 0. I've burned myself a couple of times on that one.
            0
            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund
            User avatar
            thomthom 
            PluginStore Author
            PluginStore Author
             

            Re: By value or by reference?

            Postby Dan Rathbun » Mon Mar 08, 2010 1:18 pm

            thomthom wrote:So using p2 = p1.clone is the proper way to get a copy of a point then?


            Only way if you keep it a Point3d. If you convert to Array, then you have the real 'proper' .dup and .clone that are inherited correctly from Object.

            The Geom::Point3d did inherit .dup but it does not work, it returns nil.
            And Google overrode the standard .clone, and the new one does not pass on taintedness and frozen state correctly.
            0
              I'm not here much anymore. But a PM will fire email notifications.
              User avatar
              Dan Rathbun 
              PluginStore Author
              PluginStore Author
               

              Re: By value or by reference?

              Postby thomthom » Mon Mar 08, 2010 1:28 pm

              Well, if .to_a is faster than cloning a Point3d then I can live with that. I just need to grab a copy of some x,y,z co-ordinates and modify its values - as fast as possible.
              0
              Thomas Thomassen — SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund
              User avatar
              thomthom 
              PluginStore Author
              PluginStore Author
               

              Re: By value or by reference?

              Postby Dan Rathbun » Mon Mar 08, 2010 1:33 pm

              thomthom wrote:Well, if .to_a is faster ...


              .to_a is 1 less char to type than .clone :lol:

              .. and it will create a new Array object, and since the GSUT extended the Array class with .x, .y, .z etc, it's same same...
              0
                I'm not here much anymore. But a PM will fire email notifications.
                User avatar
                Dan Rathbun 
                PluginStore Author
                PluginStore Author
                 

                Re: By value or by reference?

                Postby Dan Rathbun » Mon Mar 08, 2010 1:43 pm

                thomthom wrote:
                TBD wrote:see also The Ruby programming language By David Flanagan, Yukihiro Matsumoto

                Interesting link. I think I need to read further into that book.

                No Kidding! Yukihiro Matsumoto is "Matz" the inventor of Ruby! :ugeek:

                I didn't know Google Books had this. :thumb:
                0
                Last edited by Dan Rathbun on Tue Mar 09, 2010 1:47 am, edited 1 time in total.
                  I'm not here much anymore. But a PM will fire email notifications.
                  User avatar
                  Dan Rathbun 
                  PluginStore Author
                  PluginStore Author
                   

                  Re: By value or by reference?

                  Postby thomthom » Mon Mar 08, 2010 1:49 pm

                  Only preview of the book - not the whole thing. I just placed an order for it. I don't like reading books on screen. Hurts my eyes.
                  0
                  Thomas Thomassen — SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund
                  User avatar
                  thomthom 
                  PluginStore Author
                  PluginStore Author
                   

                  SketchUcation One-Liner Adverts

                  by Ad Machine » 5 minutes ago



                  Ad Machine 
                  Robot
                   



                   

                  Return to Developers' Forum

                  Who is online

                  Users browsing this forum: BoeffsAcc0unt and 3 guests

                  Visit our sponsors: