From: senderista@... (Tobin Baker) Date: 2001-06-22T06:21:50+09:00 Subject: [ruby-talk:16726] Simulating call-by-reference in Ruby I'm currently working on Ruby bindings for ORBit and thought that it would be nice if I could simulate call-by-reference for inout parameters. The Perl bindings for ORBit do this quite nicely, e.g.: //IDL interface Foo { void bar(inout int baz); } #Perl #somehow get reference to Foo object $myFoo #assume Foo implementation adds 1 to argument baz my $baz = 10; $myFoo->bar(\$baz); print $baz; #=> 11 As you can see, you just have to add an extra reference to each inout parameter. Python doesn't have anything like Perl's reference operator, so the mapping spec recommends passing inout parameters like in parameters, and returning them in a tuple together with the return value (if any) and all out parameters. To me this is somewhat inelegant and does a rather poor job of emulating inout semantics, but there may be no alternative in Python. In Ruby, however, we *can* simulate reference parameters by having the caller pass a symbol instead of the variable itself, getting the value of the variable for that symbol from the caller's context (using eval), and then using eval again to write another value into that variable. E.g.: baz = 10 myFoo.bar(:baz) p baz #=> 11 The problem is that there doesn't seem to be any way to access the caller's context without cooperation from the caller, e.g., having them pass a Binding object as a parameter to the method they're calling. I noticed on ruby-talk that some other people had struggled with this problem as well. I had hoped at first that caller() might give me what I was looking for, but of course it just returns a stack trace, not a Binding object. Wouldn't it be useful to have a way for any method to access its caller's context? Is anyone considering this as an addition to Ruby 1.7, or are there insurmountable implementation difficulties? (I know next to nothing about Ruby internals.) Anyway, here's the best I can do now: baz = 10 myFoo.bar(:baz, inout) p baz #=> 11 The implementation is in C, but looks something like this: class Object alias_method :inout, :binding end def bar(baz, bind) if baz.instance_of?(Symbol) eval "#{baz.id2name} += 1", bind else raise TypeError, "Argument not a symbol" end end