value by reference

F

Florian Gross

Mohammad said:
def do_something(a, b, c)
a = a + 1
b = b + 2
c = c + 3
return [a , b, c]
end

a, b, c = do_something(a, b, c)

I don't like to handle with too many return variables but I had to do it
in my real project.

Maybe you could return a Hash then?
What is lambdas? sorry.. if I am asking anything very strange !!
I will still prefer to return multiple variables in stead of using these
much code!

lambdas are objectified blocks. You can pass them around, assign them to
variables, call methods and more of the stuff you can do with Objects.

The above might look like much code, but there's millions way of making
it shorter. Here's one:

do_something { |ai, bi, ci| a += ai; b += bi; c += ci }

Invokation in the method would change to yield(1, 1, 1).

I'm still interested in your reasons for doing this. :)
 
M

Mohammad Khan

Before telling my issue, let me show my script:


def do_something(a, b, c)
a = a + 1
b = b + 2
c = c + 3
end
a, b, c = 5, 6, 7
puts "before do_something:"
puts "a : #{a}"
puts "b : #{b}"
puts "c : #{c}"
do_something(a, b, c)
puts "after do_something:"
puts "a : #{a}"
puts "b : #{b}"
puts "c : #{c}"



My issue:
I would like to see the value of a, b, c after calling #do_something as:
a = 6, b = 8, c = 10

how can I do it without making a, b, c an instance variable?
In other words, how can I send value by reference?


Thanks
MOhammad
 
T

trans.

I beleive it is by reference, the problem is you need to modify
inplace.

In this particular case you'll need an alternative to #+, b/c #+ is not
an inplace operator. But will you use, I'm not sure. #succ seems to
work inplace, but that's not to helpful. (I've a mind to RCR for a 'def
succ(n=1)', but that doesn't help you now)

It does seem like there should be clearer ways to deal with this. I
know .net for instance has very clear distinctions.
 
A

Assaph Mehr

It's probably easier if you're used to think in pointers / references.
Ignore for the moment that fixnums are special (immediate values).
def do_something(a, b, c)
a = a + 1
b = b + 2
c = c + 3
end

do_something receives 3 references in the declaration. those references
are places in three method-local variables.
in the body, it changes the local-variables to references that point to
*other* objects.


a, b, c = 5, 6, 7

you have created three local variables, referencing fixnum objects.
puts "before do_something:"
puts "a : #{a}"
puts "b : #{b}"
puts "c : #{c}"

you print the values of the objects referenced by the local variables.
do_something(a, b, c)

you called do_something, which received the references, and changed *in
the method body only* the method-local variables to point to other
objects.
puts "after do_something:"
puts "a : #{a}"
puts "b : #{b}"
puts "c : #{c}"

here you print the values referenced by the outside-scope local
variables. these local-variables have never been changed in this scope
so they point to the same fixnum objects you specified in the
beginning.

My issue:
I would like to see the value of a, b, c after calling #do_something as:
a = 6, b = 8, c = 10

how can I do it without making a, b, c an instance variable?
In other words, how can I send value by reference?

you have some options:
- global variables ($var): ugly and not recommended.
- return the new values: probably cleanest way.

def do_something(a, b, c)
a = a + 1
b = b + 2
c = c + 3
[a, b, c]
end
a, b, c = 5, 6, 7
a, b, c = do_something(a, b, c)

- create a box class: essentially a pointer. both the ouside-scope and
the method-scope local-variables point to the same box object so you
can change fields in the box object and those changes will be reflected
in all scopes.

HTH,
Assaph
 
M

Mohammad Khan

This is not easily done. First of all you should ask yourself why you
find yourself needing it and if there is not a better mechanism in Ruby
that you could use to accomplish your goal. (Methods can return multiple
values.)

I really need it.
I could do it by:

def do_something(a, b, c)
a = a + 1
b = b + 2
c = c + 3
return [a , b, c]
end

a, b, c = do_something(a, b, c)

I don't like to handle with too many return variables but I had to do it
in my real project.


After that there's two approaches to addressing the above:

1) Supply lambdas:

def do_something(inc_a, inc_b, inc_c)
inc_a.call(1)
inc_b.call(1)
inc_c.call(1)
end

do_something(
lambda { |x| a += x },
lambda { |x| b += x },
lambda { |x| c += x }
)

What is lambdas? sorry.. if I am asking anything very strange !!
I will still prefer to return multiple variables in stead of using these
much code!

2) Use variable.rb to handle variables as Objects:

def do_something(a, b, c)
a.value += 1
b.value += 1
c.value += 1
end

do_something(Variable[:a], Variable[:b], Variable[:c])

If you find yourself really needing to do this, please follow up with
your reasons. I've not yet found many cases where this is necessary and
would be interested in getting to know about new ones.
 
T

trans.

I would like to elaborate on this generally. Is ti possibel to have a
clean distinction? In other words, would to be possible to have all
objects to be modifiable inplace somehow? I know there are pathces out
there that do this, but what keeps this from being generally
acceptable?

T.
 
D

David A. Black

Hi --

Before telling my issue, let me show my script:


def do_something(a, b, c)
a = a + 1
b = b + 2
c = c + 3
end
a, b, c = 5, 6, 7
puts "before do_something:"
puts "a : #{a}"
puts "b : #{b}"
puts "c : #{c}"
do_something(a, b, c)
puts "after do_something:"
puts "a : #{a}"
puts "b : #{b}"
puts "c : #{c}"



My issue:
I would like to see the value of a, b, c after calling #do_something as:
a = 6, b = 8, c = 10

how can I do it without making a, b, c an instance variable?
In other words, how can I send value by reference?

Fixnums are immediate values, and are immutable, even when they're
wrapped in variables. So what you're trying to do is equivalent to:

do_something(5,6,7)

puts 5 * 5 # 36 -- i.e., 5 has become 6

It won't work (luckily :) because Ruby doesn't let you perform that
kind of modification on Fixnums.

With mutable objects you can do what you're describing -- for example,
adding to a string that's in a local variable:

irb(main):001:0> def x(y); y << "def"; end
=> nil
irb(main):002:0> s = "abc"
=> "abc"
irb(main):003:0> x(s)
=> "abcdef"
irb(main):004:0> s
=> "abcdef"


David
 
T

trans.

Sorry. #succ does not act inplace and nothing does on Fixnum. Its been
a while since I used VB.Net but in it you can define a subroutine with
parameters ByVal or ByRef:

Private Sub IntegerByRef(ByRef X As Integer)
Dim i As Long
For i = 1 To m_NumAssignments
X = 123
Next i
End Sub

Private Sub IntegerByVal(ByVal X As Integer)
Dim i As Long
For i = 1 To m_NumAssignments
X = 123
Next i
End Sub

Those are the two ways in VB, but Ruby is sort of inbetween. It passes
by reference, but if you reassign it looses the reference. You can
simulate by value simply by duplicating the parameter when it comes in,
but to do the other requires some trickery. One way is:

def do_somthing(a,b,c)
a[0] += 1
b[0] += 1
c[0] += 1
end
a, b, c = [5], [6], [7]
do_something(a,b,c)

But I wonder, could Ruby offer something like the VB forms without
violating immutability? Sort of an indirect reference.
Guess I don't understand why it's conidered a negative.

T.
 
F

Florian Gross

trans. said:
Sorry. #succ does not act inplace and nothing does on Fixnum.

Of course nothing can change the value of immediate Objects. :)
But I wonder, could Ruby offer something like the VB forms without
violating immutability? Sort of an indirect reference.
Guess I don't understand why it's conidered a negative.

See my earlier posting about the lambda { } and Variable[:name] ways of
doing this.

Ruby itself just treats variables as names for Objects. You can't really
refer to a variable itself, you can only refer to the Object it is a
name for. That's a surprisingly simple and non-confusing model. I think
Ruby itself should not be changed. (Though it would be nice if it had
something like Binding.of_caller built-in...)
 
G

Glenn Parker

Florian said:
See my earlier posting about the lambda { } and Variable[:name] ways of
doing this.

Sorry, but I can't believe anybody would actually want to use the lambda
styles as proposed. They are ugly and obscure.
Ruby itself just treats variables as names for Objects. You can't really
refer to a variable itself, you can only refer to the Object it is a
name for. That's a surprisingly simple and non-confusing model.

Judging by the frequency that this issue is discussed, it's more
confusing than you suggest. A typical programmers expects
call-by-reference to work one way, and Ruby works differently. Extra
confusion results because this difference is masked by using
self-updating methods, but it always fails for immediate objects, and it
eventually fails in a surprising way for non-immediate objects. I call
it surprising because a typical programmer does not expect the
assignment operator to destroy call-by-reference, but that is exactly
what happens.

def inc1(a, i); a += i; end
def inc2(a, i); a = a + i; end

To the naive Ruby programmer, inc1 and inc2 seem to be equivalent, but
Ruby gurus just shake their heads and sigh while they explain, yet
again, that there is a difference. Why is this considered a good thing? :)

You might say that the typical programmer has grown accustomed to a
confusing model, and Ruby is better off without that model. But, that
is nigh on saying that Ruby is better off without the typical
programmer. And that would be a shame, since Ruby has much to offer the
hordes of Perl and Python programmers looking for something better.

Ruby does *not* support call-by-reference, in the traditional sense of
the term. Instead, it is strictly call-by-value, and formal paremeters
are copies of references from the calling scope. If Ruby had real
call-by-reference, then it would be trivial to define a procedure that
updates a variable from its parent's scope, and inc1 and inc2 above
would be equivalent.
I think
Ruby itself should not be changed. (Though it would be nice if it had
something like Binding.of_caller built-in...)

Tcl is similar to Ruby, regarding both the style of variable passing and
the resulting confusion among its new adopters, but Tcl documentation
has always stressed the details of this issue, and the Tcl core has the
"uplevel" and "upvar" builtins. I'm not a huge fan of Tcl, but I do
think the Tcl folks handled this issue in the best way possible.
 
T

trans.

Right. I'm not suggesting that Ruby change this. I'm just wondering if
might be possible to add an extra feature that would allow for the
alternate when passing arguments through methods.

Personally, I've alwasy thought of variables as containters, so in that
way of thinking, which I think is common, one would expect to be able
to change what's in the container. I don't think Ruby's approach is
always simple for the enduser and it does lead to some surprises --for
example this very thread.

Hmm..reminds me of why I like the idea of all variables being
collections....

Binding.of_caller is useful for meta-programming, but that's bad
business for general use.

T.
 
D

David A. Black

Hi --

Florian said:
See my earlier posting about the lambda { } and Variable[:name] ways of
doing this.

Sorry, but I can't believe anybody would actually want to use the lambda
styles as proposed. They are ugly and obscure.
Ruby itself just treats variables as names for Objects. You can't really
refer to a variable itself, you can only refer to the Object it is a name
for. That's a surprisingly simple and non-confusing model.

Judging by the frequency that this issue is discussed, it's more confusing
than you suggest.

Then again, I've found that when people get confused by things in
Ruby, it's very often because Ruby is simpler and less cluttered than
they expect it to be. My favorite example of this is the singleton
class model.
A typical programmers expects call-by-reference to work
one way, and Ruby works differently. Extra confusion results because this
difference is masked by using self-updating methods, but it always fails for
immediate objects, and it eventually fails in a surprising way for
non-immediate objects. I call it surprising because a typical programmer
does not expect the assignment operator to destroy call-by-reference, but
that is exactly what happens.

def inc1(a, i); a += i; end
def inc2(a, i); a = a + i; end

To the naive Ruby programmer, inc1 and inc2 seem to be equivalent, but Ruby
gurus just shake their heads and sigh while they explain, yet again, that
there is a difference. Why is this considered a good thing? :)

We must know different Ruby gurus -- the ones I know are remarkably
gracious, even enthusiastic, about explaining things :)

In any case, I believe the two things in your example are actually
equivalent. My understanding is that Ruby always expands:

x += y

to

x = x + y

I don't think there are any cases where it makes any difference which
one you use, at least as far as I can remember.

As for confusion, typical programmers, etc.: I don't think there's as
much of the "princess and the pea" syndrome among programmers as one
might think -- most people seem to be fairly adventurous and
thick-skinned -- and people certainly have to rise above that if they
want to explore more than a rather small number of programming
technologies. Besides, languages with other models exist already.
Ruby also exists, and there's no more reason for Ruby to converge on
the model of some other language than for some other language to
converge on Ruby. (Maybe even less :) Away with the Ruby
inferiority complex! :)
Ruby does *not* support call-by-reference, in the traditional sense of the
term. Instead, it is strictly call-by-value, and formal paremeters are
copies of references from the calling scope.

This is the key to it, in my opinion. Every "value" in Ruby is a
reference, and every reference to an object is the same distance from
the object as every other reference to that object (as in: a =
Object.new; b = a; a and b are now equivalent with respect to
their distance from the object).


David
 
A

Alexander Kellett

Right. I'm not suggesting that Ruby change this. I'm just wondering if
might be possible to add an extra feature that would allow for the
alternate when passing arguments through methods.

sorry if this offends, but there is no less blunt way to say it.
if anyone need it. they've gone wrong already.
the solution: design

alex
 
M

Michel Martens

It's easy to accomplish this task with strings:

def do_something(a, b, c)
a.replace((a.to_i + 1).to_s)
b.replace((b.to_i + 2).to_s)
c.replace((c.to_i + 3).to_s)
end

a, b, c = '5', '6', '7'
do_something(a, b, c)

It would be nice to have a replace method for every object, then we could write:

def do_something(a, b, c)
a.replace(a + 1)
b.replace(b + 2)
c.replace(c + 3)
end

a, b, c = 5, 6, 7
do_something(a, b, c)
 
D

David A. Black

Hi --

It's easy to accomplish this task with strings:

def do_something(a, b, c)
a.replace((a.to_i + 1).to_s)
b.replace((b.to_i + 2).to_s)
c.replace((c.to_i + 3).to_s)
end

a, b, c = '5', '6', '7'
do_something(a, b, c)

It would be nice to have a replace method for every object, then we could write:

def do_something(a, b, c)
a.replace(a + 1)
b.replace(b + 2)
c.replace(c + 3)
end

a, b, c = 5, 6, 7
do_something(a, b, c)

What would you replace 5 with? :)

(Remember, you're sending the 'replace' method to an *object*, not an
identifier.)


David
 
M

Michel Martens

What would you replace 5 with? :)

(Remember, you're sending the 'replace' method to an *object*, not an
identifier.)

Hi, David. I know how it works now, that's why it's a proposal. The
idea would be to modify the language to allow that kind of
manipulation. Then, the following methods would be allowed:

a = 'hello world' # String
a.replace(/\w+/) # Regexp
a.replace(35) # Fixnum
a.replace(SomeClass.new) # SomeClass

And then you would be able to add methods like to_s! or to_i!, etcetera.

Michel
 
S

Stefan Lang

Michel said:
It's easy to accomplish this task with strings:

def do_something(a, b, c)
a.replace((a.to_i + 1).to_s)
b.replace((b.to_i + 2).to_s)
c.replace((c.to_i + 3).to_s)
end

a, b, c = '5', '6', '7'
do_something(a, b, c)

It would be nice to have a replace method for every object, then we could
write:

def do_something(a, b, c)
a.replace(a + 1)
b.replace(b + 2)
c.replace(c + 3)
end

a, b, c = 5, 6, 7
do_something(a, b, c)

But replace doesn't replace the object the variable
points to, it just replaces instance variables of the
string object:

irb(main):001:0> s = "abc"
=> "abc"
irb(main):002:0> s.object_id
=> 538462462
irb(main):003:0> s.replace "xyz"
=> "xyz"
irb(main):004:0> s
=> "xyz"
irb(main):005:0> s.object_id
=> 538462462

You can write your replace method if you like:

class A
attr_reader :ivar
def replace(a_obj)
@ivar = a_obj.ivar
# or generally copy all
# instance vars
end
end

def do_something(obj)
...
obj.replace(other)
end

a = A.new
do_something(a)
p a
 
A

Alexander Kellett

Hi, David. I know how it works now, that's why it's a proposal. The
idea would be to modify the language to allow that kind of
manipulation. Then, the following methods would be allowed:

a = 'hello world' # String
a.replace(/\w+/) # Regexp
a.replace(35) # Fixnum
a.replace(SomeClass.new) # SomeClass

And then you would be able to add methods like to_s! or to_i!,
etcetera.

replace already exists in string and makes a lot of sense.
for what its worth i just had the need for the above, if you
want a quick hack solution. go for this:
class Ref < SimpleDelegator; def replace obj; __setobj__ obj; end;
end
its slow as heck, but at least you'll just be able to code
away and eventually replace it with a better design which
doesn't require such crap.

ruby is a happy medium between a functional language without
any side effects whatsoever and most of the other side effect
ridden languages (perl is an awful example) of these. i'd prefer
to see ruby stay as it is.

sure, maybe its difficult for you to see redesign just yet,
but you'll have to do so in any case. the use of such misdesign
will just get you further down the well...

Alex
 
D

David A. Black

Hi --

Hi, David. I know how it works now, that's why it's a proposal. The
idea would be to modify the language to allow that kind of
manipulation. Then, the following methods would be allowed:

a = 'hello world' # String
a.replace(/\w+/) # Regexp
a.replace(35) # Fixnum
a.replace(SomeClass.new) # SomeClass

And then you would be able to add methods like to_s! or to_i!, etcetera.

I guess that's similar to the "become" idea that people have discussed
at various times. I personally see it as a solution in search of a
problem, but I know it's popular with the meta-meta-meta-3vi1 crowd
:)


David
 
T

trans.

sorry if this offends, but there is no less blunt way to say it.
if anyone need it. they've gone wrong already.
the solution: design

That's silly. By that line of reasoning, nearly every other language
has got it wrong. Wrong must be pretty good since Ruby is no where near
as popular as those languages that can do this sort of thing.

I think the problem with Ruby is that it _can be done_ if you use
certain _types_ of objects, but not others. That to me goes against the
feather of our friendly duck.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top