Request: arguments by reference

Would be possible to include the option to pass arguments by reference
instead of by value?

def swap(a, b)
tmp = a
a = b
b = a
end

a = “A”
b = “B”
swap(a, b)
puts a, b # “A”, “B”

Because Ruby passes arguments by value any attribution will change only
the arguments not the variables. My sugestion is to use some way of
indicating that the argument is a reference and that would allow the
above example to work.
I don’t know if this will mess things up, but I guess the difference is
only instead of creating a new variable, “tell” the intrepeter to use
the variable passed as argument. But that can break something…

I know the above example can be done like ‘a, b = b, a’, but this always
obliges to set things directly and never allow to use functions, that,
in my opinion, is a limitation. The actual way forces the programmer to
know if any particular method creates or not a new object. For instance:

def append_str(str, append)
str << append
end

def add_str(str, add)
str += add
end

a = “A”
b = “B”

append_str(a, " + something")
add_str(b, " + nothing")

puts a, b # “A + something”, “B”

<< operator changes the object itself so a will be changes, += creates a
new object so b won’t be changed. Taking into account that Ruby uses
mainly references for each object (fixnum and company are the
exceptions) I hope this would be possible to include.

Thomas B. wrote:

The = sign after a variable name
assigns a new value to this variable (…)

Sorry. What I said is not what I meant, and is not correct. This
sentence ought to be:

The = sign after a variable name assigns a new variable to this name
(…)

TPR.

Pedro S. wrote:

Would be possible to include the option to pass arguments by reference
instead of by value?

I think not. In Java you cannot pass by reference, and that’s not
because Java is a poor language where things cannot be done easily.
That’s because Java enforces other way of programming than, say C. It’s
Object Oriented programming, namely.

Passing by reference is adding mess. The = sign after a variable name
assigns a new value to this variable, and let this be that way.
Similarly += and the family.

If you need badly the variables to really change values, do what should
be done in an object oriented language: wrap them in classes, and add
accessors. That’s the way you’d also do it in Java.

The actual way forces the programmer to
know if any particular method creates or not a new object.

In fact, programming forces the programmer to know how to programme. And
knowing what creates a new object and what not, is part of this
knowledge. And in Ruby it’s not very hard to guess.

Taking into account that Ruby uses
mainly references for each object (fixnum and company are the
exceptions) (…)

In fact Ruby always passes the reference to an object by value, no
matter if it is Fixnum or whatever. The only difference is that Fixnums
(and some others) are immutable, so they simply do not have methods like
<< that change their values in-place. Ruby behaves the same way with any
class of arguments, it’s the class itself that does or does not allow an
in-place change.

TPR.

Hi Thomas,

If you need badly the variables to really change values, do what should
be done in an object oriented language: wrap them in classes, and add
accessors. That’s the way you’d also do it in Java.

This is obviously a “solution” but with considerable performance
penalty. It’s like using C pointers to alter values, so if you need to
alter a pointer’s value you have a pointer to a pointer and so on… At
least in C you don’t need to encapsulate everything so you have small
performance penalty.
For instance, if I call a method that calls another method to change the
value I need to encapsulate this two times, that is, I need to
encapsulate each time I call a function to allow it to alter the value.

In fact, programming forces the programmer to know how to programme. And
knowing what creates a new object and what not, is part of this
knowledge. And in Ruby it’s not very hard to guess.

It’s very different to know how to programme than to know what a
specific method/operator does. Regarding object creation you’re right,
unless you use strange libraries there’s not hard to know what changes
and what does not. Suppose a Ruby implementation where += behaves like
<<, the final result is the same so I guess this complies with Ruby
language specification, but the programmer has to take that into
account…

In fact Ruby always passes the reference to an object by value, no
matter if it is Fixnum or whatever. The only difference is that Fixnums
(and some others) are immutable, so they simply do not have methods like
<< that change their values in-place. Ruby behaves the same way with any
class of arguments, it’s the class itself that does or does not allow an
in-place change.

When I said by value I should have written reference by value, my
mistake. That’s again the problem of encapsulation, the main reason
behind, for instance, a Fixnum being immutable is performance. If that
didn’t meant performance penalty, Ruby wouldn’t be implemented this way.
The same applies for what I called “company” (symbols, …).

I understand your point, I just wanted to have a simple way to do that
as in C++, avoiding an encapsulation for each function invocation. Ruby
is an awesome language and im my opinion what’s holding it back is it’s
performance, thinking in a way that has even worse performance isn’t a
“solution” for me.

Pedro.

Hello Pedro.

This is obviously a “solution” but with considerable performance
penalty. It’s like using C pointers to alter values, so if you need to
alter a pointer’s value you have a pointer to a pointer and so on…

Well, of course there is some performance penalty, but I guess it is not
that fatal. I don’t know the actual implementation of accessors in Ruby,
but I think that the time penalty could be really low, and the memory
penalty can be reduced by encapsulating logical group of variables in
one class (which should be done anyway). I think that if they decided
not to include passing by reference in Ruby (and also in Java), then
they had some good solution in mind, and this solution cannot be as bad
as you paint it.

For instance, if I call a method that calls another method to change the
value I need to encapsulate this two times, that is, I need to
encapsulate each time I call a function to allow it to alter the value.

Here I don’t understand - you need to encapsulate the field only when
you want to pass by reference, so if you have a variable, and a chain of
method that you want to be able to alter its value, then you have to
encapsulate it only once, and pass the encapsulating class to the chain.
I suppose that this “modify pointer to the pointer” thing is not very
often needed.

Suppose a Ruby implementation where += behaves like
<<, the final result is the same so I guess this complies with Ruby
language specification (…)

It does not, as far as I know. You cannot redefine += and other /.?=/
operators in Ruby, so I think it is ensured that they do create a new
variable.

I agree that somebody could redefine << so that it returns a new
variable, but this is simply an example of a bad thing to do. It’s like
redefining the ‘operator ,’ in C++ - a very very bad thing to do, and I
wouldn’t use such a library that does so. So still I think there is
always a way to tell an in-place changer from a const function easily,
and for me the whole question doesn’t seem to be a problem.

I can understand that you want passing by reference to be available as
an option, but in my opinion it is not possible to do it without some
very deeply going changes in the language. Surely the = sign should be
left for creating a new variable, and as bare pointers are not allowed
in Ruby, currently I don’t have any good idea how pass-by-reference
could be done. You would also have to control the lvalue capabilities of
expressions, which doesn’t have to be done currently. For example, what
if I pass by reference an expression like a.b, where b is an accessor,
or arr[x]? Will it change the original underlying variable, or will it
raise an error? Error at compilation, or at runtime?

Also I think that in a well designed program, the situations where you
need such behaviour would not exist. Of course performance is important,
but I think that still the most important thing is the ability to create
a nice, readable and structured code, so I would definitely choose
encapsulating over changing the language.

TPR.

Pedro S. wrote:

The main need for references is to allow primitive/immutable types to be
treated “as objects”. Even if the only thing that Ruby used to implement
references was the object encapsulation, at least you have that option
and don’t need to be doing that all the time it needs to be done. Being
inside Ruby it would be certainly faster than user made code. If you
think in C pointers or C++ references that’s what they really are -
“capsules”. I think it’s preferable to have this option even if it isn’t
as performant, but the programmer has the choice.

So I think that the best solution could be not to add syntax for passing
by reference, but to add types like MutableFixnum (and others), that
would behave exactly like Fixnum, plus they would have method replace,
working a bit like Array#replace - changing the value without creating a
new object. In this way, all old code would work as before, and as fast
as before, and also there would be no chance of accidentally changing
value of an object that should not be changed (like calling
a.b.replace(x) even though a.b= is not defined and it is crucial for the
program that it is not). You would be able to change only object
declared as MutableSomething. It wouldn’t also mess things up with =.

Probably not in 1.9, but maybe later it could make some sense to think
about how to implement it in the core.

Th.

On Sat, Sep 06, 2008 at 08:59:01AM +0900, Pedro S. wrote:

b = “B”
swap(a, b)
puts a, b # “A”, “B”

Because Ruby passes arguments by value any attribution will change only
the arguments not the variables. My sugestion is to use some way of
indicating that the argument is a reference and that would allow the
above example to work.
[…]

First off, you’re talking about a rare need. It’s generally poor
practice
to add syntax to serve a rare need. Instead, you need an idiom to take
care
of it on the rare occasions when you need it. For your simple swap
example
above, the idiom doesn’t even involve a function:

a,b = b,a

That uses an implicit array. For more complex examples you use an
explicit
array:

def increment_values(values)
values.map! { |v| v.succ }
end

a = 1
b = 2
c = 3
foo = [ a, b, c ]
increment_values(foo)
a,b,c = foo

Given the acceptable ease with which you can fulfill your rare pass by
reference needs with existing syntax, the marginal additional value of
simpler syntax is overwhelmed by the marginal additional complexity such
syntax requires.

–Greg

Hi,

Well, of course there is some performance penalty, but I guess it is not
that fatal. I don’t know the actual implementation of accessors in Ruby,
but I think that the time penalty could be really low, and the memory
penalty can be reduced by encapsulating logical group of variables in
one class (which should be done anyway). I think that if they decided
not to include passing by reference in Ruby (and also in Java), then
they had some good solution in mind, and this solution cannot be as bad
as you paint it.

In my opinion there are essentially two reasons:
1 - Everything is supposed to be an object;
2 - Anything that needs to be altered is inside the passed object.

If everything is an object than everything is “encapsulated”, so when
you pass the object’s reference value you can change that object in any
way you want.
If you need to swap anything, that must be done inside any particular
object.

I guess they are counting on this two things. But once again, if this
rules were perfect Java won’t have primitive data types, nor Ruby would
have immutable objects.

Also I think that in a well designed program, the situations where you
need such behaviour would not exist. Of course performance is important,
but I think that still the most important thing is the ability to create
a nice, readable and structured code, so I would definitely choose
encapsulating over changing the language.

That would be almost true if there weren’t primitives nor immutable
objects, but that’s not the case. I may be wrong, but who decided that
these mecanisms are enough was thinking in the solution you gave, that
represents a small amount of cases. The other solution (in Ruby) is to
return as result all altered variables in a specific order and assigned
them to variables you want to alter (I guess it’s known as
call-by-value-return).

The main need for references is to allow primitive/immutable types to be
treated “as objects”. Even if the only thing that Ruby used to implement
references was the object encapsulation, at least you have that option
and don’t need to be doing that all the time it needs to be done. Being
inside Ruby it would be certainly faster than user made code. If you
think in C pointers or C++ references that’s what they really are -
“capsules”. I think it’s preferable to have this option even if it isn’t
as performant, but the programmer has the choice.

Pedro.

2008/9/6 Pedro S. [email protected]:

Would be possible to include the option to pass arguments by reference
instead of by value?

Maybe.

I know the above example can be done like ‘a, b = b, a’, but this always
obliges to set things directly and never allow to use functions, that,
in my opinion, is a limitation.

Did it ever occur to you that others might actually consider this a
liberation? If you introduce call by reference the way you suggest
you cannot be sure that the instance you assigned to a variable is
still the same after method calls. This can lead to subtle bugs.

The actual way forces the programmer to
know if any particular method creates or not a new object.

Regardless of language features the user of a function or method (or
class for that matter) needs to know how it behaves. You need proper
documentation anyway.

For instance:

def append_str(str, append)
str << append
end

def add_str(str, add)
str += add
end

There is no point in implementing these methods. They do to little.
And btw, you would rather do

def add_str(str, add)
str + add
end

<< operator changes the object itself so a will be changes, += creates a
new object so b won’t be changed. Taking into account that Ruby uses
mainly references for each object (fixnum and company are the
exceptions) I hope this would be possible to include.

Even if it was. I cannot recall ever having felt the need for this.
This could mean anything from “my personal programming style is
special in that it does not lead to code that would need references”
to “the general Ruby style does not need references” - maybe you did
not get the hang of it yet. The fact that you use pretty artificial
examples seems to indicate that this is purely academic and there is
no real programming need - even for yourself.

Kind regards

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs