value by reference

M

Mohammad Khan

Mohammad said:
But what about scenario 2? [methods changes state of an Object that
it gets as an argument] Scenario 2 is not acting as scenario 1, is it
because scenario 2 gets object rather than variable? Or, Scenario 2
gets clonable object while scenario 1 not?

First, let's agree on using the term "mutable" (or "changeable") instead
of "cloneable". (Immutable objects can not be cloned most of the time,
but the both terms are not strictly the same things.)

agreed on using term 'mutable'.
Scenario 2 changes attributes of an Object. This is something that is
entirely possible. It makes sense for a CarFactory object to be stopped
or running -- it also makes sense that you are able to stop or (re)start
such an object at run time. What can not be done is changing the value
of a variable that appeared in the method invocation because the method
does not know anything about the variable -- it gets the Object. Objects
can have state that can be changed. This can happen via accessors that
are invoked like obj.foo = x or other methods like car_factory.stop.
But while obj.foo looks similar to variable assignment it is something
entirely else.

Why do different things look so similar in Ruby? It's uniform access at
work.

In other languages there usually is the distinction between Object's
fields and methods. Having public fields is usually a bad idea (it
breaks encapsulation) and looks like this:

obj.field += 5

Having methods that modify state looks like this:

obj.setField(obj.getField() + 5)

In Ruby both look like this:

obj.field += 5

Even if obj.field=() or obj.field() do not directly map to an instance
variable at all like in this case:

def obj.radius()
@diameter / 2
end

def obj.radius=(new_radius)
@diameter = new_radius * 2
end

I hope this explains how Ruby works. If there is still anything left
that you don't understand, feel free to ask.

Thanks for your GREAT explanation.

In my two scenarios, we were dealing with two things: variable and object.
If everything is object ... variable is coming from where?
In other words, what is the relation between variable and object.
Are non-mutable objects considered as variables?


Thanks again,
MOhammad
 
A

Austin Ziegler

I understand that. But what about scenario 2? Scenario 2 is not
acting as scenario 1, is it because scenario 2 gets object rather
than variable? Or, Scenario 2 gets clonable object while scenario
1 not? Thanks, Florian.

The distinction is not between clonable objects and non-clonable
objects, AFAICT. It's between immediate and value objects in this
particular case, but the real problem is that you're exhibiting a
confusion between variables and objects.

-austin
 
A

Andreas Semt

Florian said:
Andreas said:
You can change the Objects that you're methods gets in case they are
value Objects [...]

A nice discussion.
Florian should write a book! :)


Thanks, but I just spotted myself using "you're" instead of "your".
Everything's going downhill for sure.

It's a change for the worse.
Can we all pretend that it didn't happen? ;)

Yes, we can! But it wouldn't help! ;-)
Greetings,
Andreas
 
A

Austin Ziegler

Isn't everything *object* in Ruby?
Now you know, what I am after ?!

Yes, and no.

a = 1
b = 2
c = 3

The values 1, 2, and 3 are objects. a, b, and c are not objects.

def foo(a, b, c)
end

In #foo, a, b, and c are most definitely NOT objects -- they're
variables that (will) contain references to objects.

In Ruby, variables are names, not memory slots.

a = b = 1

The real memory slot is more or less identified by Object#id. The
variable is just a convenience label for that object. Change the
object that the label is pointing to, and you just change the
position of the label's name. You're not actually changing the
memory location involved.

What you're after is something you shouldn't do with Ruby. Rethink
your design.

-austin
 
A

Austin Ziegler

In my two scenarios, we were dealing with two things: variable
and object. If everything is object ... variable is coming from
where? In other words, what is the relation between variable and
object. Are non-mutable objects considered as variables?

Different things entirely.

Variables are labels, names. They aren't objects. They're ways that
we, the programmers, can refer to objects.

In general, we can't do any operations against variables, because
the name is discarded at the time of execution -- only the object
exists.

-austin
 
A

Aredridel

See my earlier posting about the lambda { } and Variable[:name] ways of
Sorry, but I can't believe anybody would actually want to use the lambda
styles as proposed. They are ugly and obscure

Rightly so. I can't see any reason for .succ! to exist, really, and
only very rarely use !versions of methods anyway. The functional style
has kept a lot of bugs out of my programs.
 
S

Stefan Lang

Mohammad said:
Mohammad said:
But what about scenario 2? [methods changes state of an Object that
it gets as an argument] Scenario 2 is not acting as scenario 1, is it
because scenario 2 gets object rather than variable? Or, Scenario 2
gets clonable object while scenario 1 not?

First, let's agree on using the term "mutable" (or "changeable") instead
of "cloneable". (Immutable objects can not be cloned most of the time,
but the both terms are not strictly the same things.)

agreed on using term 'mutable'.
Scenario 2 changes attributes of an Object. This is something that is
entirely possible. It makes sense for a CarFactory object to be stopped
or running -- it also makes sense that you are able to stop or (re)start
such an object at run time. What can not be done is changing the value
of a variable that appeared in the method invocation because the method
does not know anything about the variable -- it gets the Object. Objects
can have state that can be changed. This can happen via accessors that
are invoked like  obj.foo = x  or other methods like  car_factory.stop.
But while  obj.foo  looks similar to variable assignment it is something
entirely else.

Why do different things look so similar in Ruby? It's uniform access at
work.

In other languages there usually is the distinction between Object's
fields and methods. Having public fields is usually a bad idea (it
breaks encapsulation) and looks like this:

obj.field += 5

Having methods that modify state looks like this:

obj.setField(obj.getField() + 5)

In Ruby both look like this:

obj.field += 5

Even if obj.field=() or obj.field() do not directly map to an instance
variable at all like in this case:

def obj.radius()
@diameter / 2
end

def obj.radius=(new_radius)
@diameter = new_radius * 2
end

I hope this explains how Ruby works. If there is still anything left
that you don't understand, feel free to ask.

Thanks for your GREAT explanation.

In my two scenarios, we were dealing with two things:  variable and
object. If everything is object ... variable is coming from where?
In other words, what is the relation between variable and object.
Are non-mutable objects considered as variables?

You have to tell ruby what object you want to pass
in a method or to what object a message should be sent.
A variable is just a name for an object.

def do_something(a)
# inside this method you can access
# the object passed to the method with the name a
...
end

x = Object.new
# You can do something with the new created
# object by specifying its name, the variable x

# Tell ruby to pass the object named by x
# to the method do_something
do_something(x)
# Inside do_something the method can access
# our object with the name a (look above)
 
M

Mohammad Khan

Yes, and no.

a = 1
b = 2
c = 3

It would be great if we can do
a = Integer.new(1)
b = Integer.new(2)
c = Integer.new(3)

and we can pass object a, b, c rather than variable a, b, c.

Thanks Austin and Florian for explaining variables and object.
 
T

trans.

It also has NOTHING to do with duck-typing or POLS.
Stop misusing those terms.

Never mentioned POLS. As for ducky nature, I'm simply referring to it
by analogy. Can I not make an analogy? (Is it that you don't understand
my analogy. Do I need to explain it better? If so I'm sorry for not
explaining better.)

Personally, I think you all get too worked up over it. I know how it
works, you don't need to explain it for the millionth time (at least
not to me). I wouldn't recommend being steamed about explaining it to a
newbie either, that's enevitable, and will just chase them away.

Someone mentioned performance to which I say: performace isn't
everything. Having the _option_ doesn't hurt anything in the way of
performance here either.

Bad design? Maybe. But encasulating control doesn't seem bad to me.
Lets say I have list and I pass that list to an object via
#put_you_thing_on_the_list, is that bad design? If not, why is asking
it to #put_your_number_in_my_variable so bad?

Personally I am of the opinion that programmers should be allowed to
program their way. If you constrain them b/c it isn't "proper" we may
never discover new interesting ways to do things never before
considered.

Having said that, I personally like the more obvious consitentcy that
comes form pure by-ref or by-val, and the choices offered by VB.net,
rather then Ruby's sole by-ref-to-val. But in either case, in practice
it is only occasionally an issue, and there are too many other things
to like about Ruby to overly worry about it.

BTW this is why I started the suby-ruby mailing list. To talk about
potentialites; to ask _what-if_ Ruby were like such and such --simple
exploration and expression of opinions. For some reason, when ever
these kinds of things come up on ruby-talk there is odd defensives that
goes up as if the crown jewels were in peril.

Personally I'm just express my likes and dislikes --regardles of how it
might work. Then attempt to understand the full ramifications,
disadvantage and advantage, of all approaches.
 
F

Florian Gross

Mohammad said:
It would be great if we can do
a = Integer.new(1)
b = Integer.new(2)
c = Integer.new(3)

Which would be Objects whose values can be changed?

I don't know, I think I would find it confusing if I'd do five =
Integer.new(5); some_method(five) and if after that five * five would
not be 25.
 
M

Mohammad Khan

Which would be Objects whose values can be changed?

I don't know, I think I would find it confusing if I'd do five =
Integer.new(5); some_method(five) and if after that five * five would
not be 25.

In this instance it would be confusing.
But using this concept...
I would be able to do what I wanted to do (please see my original posting)


Thanks,
Mohammad
 
M

Mark Hubbart

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)

String#replace doesn't change the object the variable refers to, it
just modifies the contents of the string; the internal state of the
same object. This can't be done with integers and symbols, for
example, because they are immutable. And crossing types would be
impossible. So, you really don't want String#replace for everything
else, you want something new.

There have already been several good explanations of why variables
don't act this way in ruby, so I'll skip that. I'll just say while
ruby's method is diferent from any other language I've worked with, it
is not inconsistant, and once I figured out the model, I found other
ways to do things than via "pass by reference". I still end up wanting
to do things in the caller's scope (binding) occasionally, but that's
not the same issue.

That said, just about anything is possible in Ruby, so here you have
it: a Ref class.

class Ref
instance_methods.each{|m| undef_method(m)}

def self.new(obj)
ref = allocate
ref.become obj
ref
end

def method_missing(*args, &block)
@ref.__send__(*args, &block)
end

def become(obj)
old = @ref
@ref = obj
old
end

def __value__() @ref end
end

when you call Ref.new(obj), you get back a Ref object, which will
appear in every way to be the "obj" that you passed to Ref.new. It
will give the same id, behave the same, respond to the same methods,
etc.

Only two differences (that I see):
First, it responds to two extra methods: __value__ and become. become
replaces the object that is being referenced, and returns the old
value. __value__ returns the object being referenced, without the Ref
wrapper. You should use this method any time you want to serialize or
Marshal the value.
Second, it circumvents the public/private method checks, so you can
call private methods directly on the reference. Sorry. Don't have the
time to figure out how to fix that without eval.

Examples:

def do_something(a,b,c)
a.become a+1
b.become b+2
c.become c+3
end
==>nil
a,b,c = Ref.new(2), Ref.new(4), Ref.new(6)
==>[2, 4, 6]
do_something(a,b,c)
==>6
[a,b,c]
==>[3, 6, 9]
do_something(a,b,c)
==>9
[a,b,c]
==>[4, 8, 12]


a = Ref.new(12)
==>12
a.id
==>25
a.become a.to_f
==>12
a
==>12.0
a.id
==>2938980
a.become a.to_s
==>12.0
a
==>"12.0"
a.id
==>2927800

In closing, while this was a fun exercise to code, I doubt I'll ever
use it :) It's the wrong hammer for my particular nails.

cheers,
Mark
 
T

trans.

Alexander said:
yes
i've coded in c++ also in which pass by ref is possible
and abhor it
pass by ref is just plain evil
pass by ref in which the *caller* states that
its a ref, (as in c via a ref and a de-ref of ptrs),
is okay in my books, but implicit anything sucks

Actually, I absolutely agree with you. I do beleive in functional
design. the idea that the effect are coming out on the left side and
the input is gogin in on the right. Very good. Unfortunately Ruby isn't
pure by-val. I don't know why exactly, maybe there are good reasons
--probably performace related. But since it isn't by-val I don't think
it does a whole lot of good to a have a partial barrier. The fact is,
one must be aware the parameters going in to a method, might be altered
in route. Giving the odus of duck-typing, i.e. we may not know what
type of object is being fed our methods necessarily, this might or
might not happen dependent soley on the type of object.

A quick example just to make myself clear:

class A
def mud(x) ; x + 1 ; end
end

class B
def mud(x) ; @x += 1 ; end
end

def quasi_mud(x)
x.mud
end

a = A.new
b = B.new

quasi_mud(a) # a remains just as it was
quasi_mud(b) # b is no longer the same

T.
 
M

Michel Martens

you should have a look at the Object#become that evil-ruby implements.
(See evil.rubyforge.org)

David: evil-ruby looks like a great efford, thank you for pointing that out.

Actually I've never had the need for this hack, I just wanted to share
my opinion. That said, I think many people gets way too defensive
(offensive?) when this kind of issues arise. Lots of virtual ink is
wasted explaining why it won't work in the current model insted of
taking a look at the benefits it could bring.

So far, the cons are two:

1. The current model doesn't support it.
2. The performance would be poor:

My opinion is that the programmer should be able to chose the
perfomance level he/she wants. About the ruby model, I'm happy with
the current implementation but maybe that statement ("ruby doesn't
work that way") is enough to stop any further improvement.
 
F

Florian Gross

Mark said:
when you call Ref.new(obj), you get back a Ref object, which will
appear in every way to be the "obj" that you passed to Ref.new. It
will give the same id, behave the same, respond to the same methods,
etc.

Only two differences (that I see):
First, it responds to two extra methods: __value__ and become. become
replaces the object that is being referenced, and returns the old
value. __value__ returns the object being referenced, without the Ref
wrapper. You should use this method any time you want to serialize or
Marshal the value.
Second, it circumvents the public/private method checks, so you can
call private methods directly on the reference. Sorry. Don't have the
time to figure out how to fix that without eval.

Third:

Ref.new(false) or Ref.new(nil) do not act like you would expect them to
in conditional contexts:

do_something if ref # always done
x = ref || y # x is always ref

Fourth:

Some of Ruby's C methods want their arguments to be instances of a
particular class. They won't even call the usual #to_x methods.
str.scan(ref) is one example of that.

Fifth:

Object.instance_method:)inspect).bind(ref).call calls the #inspect
method of the ref, not of the Object it refers to.
 
F

Florian Gross

Michel said:
Actually I've never had the need for this hack, I just wanted to share
my opinion. That said, I think many people gets way too defensive
(offensive?) when this kind of issues arise. Lots of virtual ink is
wasted explaining why it won't work in the current model insted of
taking a look at the benefits it could bring.

So far, the cons are two:

1. The current model doesn't support it.
2. The performance would be poor:

[...] but maybe that statement ("ruby doesn't
work that way") is enough to stop any further improvement.

I disagree. I think there are some core principles of Ruby that make it
Ruby. These should not change, especially not if there are no good
sample situations that would require the change to work correctly.

I'm not a conservative, but Ruby can not be everything for everyone,
part of its attractiveness is that it is simple and consistent. If we
keep adding everything that is requested that will not be true any more.

I don't have anything against trying out this kind of ideas, hell, I've
even done so repeatedly by myself, but there's a huge difference between
requesting a change (or asking why it is not like that) and toying
around with the idea.

Toying around with ideas is IMHO a nice thing as it provides a way of
testing new ideas without risking a complexity explosion in the main
language. If the feature turns out to be worthwhile or important it can
after all still be added.

matz has one of the hardest jobs I can possibly imagine. If he does add
something to Ruby that later turns out to be a bad idea he will have to
slowly deprecate it and find a way around it. At that time it might also
be too late however. I can certainly understand him being so careful
about adding new things whose implications can not be seen up front.
It's hard to do the right thing when adding new features is so easy and
removing them is so hard. Maintaining overall simplicity however
requires refactoring and removing stuff and breaking compatibility is
frequently not an option.
 
F

Florian Gross

Mohammad said:
In this instance it would be confusing.
But using this concept...
I would be able to do what I wanted to do (please see my original posting)

There's other ways that work without changing the language. They were
already posted.

Your original sample was also fairly abstract, if you were to post the
real code of you that you think needs this features, changing of getting
help would certainly be better. As of now this just discussing abstract
issues without a real world background.
 
J

Jim Weirich

trans. said:
Personally, I've alwasy thought of variables as containters,

A perfectly good way to think of variables in FORTRAN, Ada, Pascal,
Eiffel, C, C++, C#, Java, FORTH and Algol. In these languages variables
are containers into which you put values (I call this the shoebox model of
variables).

However, it is misleading in Python, Lisp, Scheme and, of course, Ruby.
In these languages, thinking of assignment as binding (associating) a name
to a value is more productive in that you can reason about the language
purely in terms of objects and names associated with objects. No need to
introduce the concept of references. And the difference between immediate
objects and reference objects (almost[1]) melts away.

For more thoughts on this, see:
http://onestepback.org/index.cgi/Tech/Ruby/Shoeboxes.rdoc. For an example
of "breaking" the rules and re-introducing references in the mix, see:
http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc.

--
-- Jim Weirich (e-mail address removed) http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

[1] Almost, but not quite. Immediate objects still can't have singleton
methods.
 

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,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top