Value by reference

Here, I agree with you.
certain _types_ of object are (probably) : clonable and not clonable

Mohammad

···

On Wed, 2005-01-19 at 11:01, trans. wrote:

> 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.

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.

No, it's not silly. Consider that C didn't have reference arguments
until late in life (I don't remember offhand whether it's mentioned
in my K&R'89 covering ANSI C). You had to use pointers -- and
references came about because pointer math was simply asking for
trouble. You needed this because C couldn't return more than one
value from a function (usefully).

Ruby isn't constrained the way that C was, needing pointers and
references the same way.

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.

WRONG. Wrong in every way. Some objects permit the in-place
modification of parts of their state. Others do not. Just because
you can do:

  a << i

if "a" refers to an Array, String, or other objects where #<< is
defined doesn't make it a special exception. #<< isn't assignment;
it's appending. a += i *is* assignment, and it follows the very
*clear* rules that Ruby has for variables and objects. #+ is
supposed to add two object instances together into a third object,
not modify one of the objects in place.

Convention? You bet. But it's consistent, at least, which is more
than can be said for most of those languages that need call-by-
reference.

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

-austin

···

On Thu, 20 Jan 2005 01:01:01 +0900, trans. <tsawyer@gmail.com> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

trans. wrote:

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.

No, other languages use other models that need this. They don't work like Ruby which is why they need it. Ruby needs other features that those languages don't have in certain cases, but over all I have to say that Ruby did a good job at being simple and consistent which is one of the top reasons I like it so much. Everything just makes sense once you understand the basics.

There's multiple approaches to this, but they should not be mixed.

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.

No, it can not be done. You can never modify a variable that appeared in your method invocation. You can change the Objects that you're methods gets in case they are value Objects, but that's how OOP works. It makes sense to be able to have entities that can change their state at run time.

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

···

On Wed, 2005-01-19 at 13:41, Florian Gross wrote:

Mohammad Khan wrote:

> 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.

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 :slight_smile: It's the wrong hammer for my particular nails.

cheers,
Mark

···

On Thu, 20 Jan 2005 00:11:40 +0900, Michel Martens <blaumag@gmail.com> wrote:

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)

Florian Gross <flgr@ccan.de> writes:

Mohammad Khan wrote:

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.

I disagree. a simply is an *reference to an* Integer, initalized with
5. Just like String.new("foo") is a String containing "foo", for
example.

Maybe we could have mutable Integers if they get created with .new?

···

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Glenn Parker said:

Perl generally uses call-by-value, but it also supports
call-by-reference using the backslash operator:

   sub inc {
     $arg = shift @_;
     $$arg += 1;
   }
   $x = 1;
   inc(\$x);
   print $x;

Perl does it by creating a reference (with a backslash) and then
dereferencing the reference (with an extra $).

If you want the same in Ruby (with only a bit heavier syntax ... ref{:x}
instead of \$x and arg.value instead of $$arg), you could write:

  def inc(arg)
    arg.value += 1
  end
  x = 1
  inc(ref{:x})
  puts x # => 2

See http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc for
details on how to implement ref.

···

--
-- Jim Weirich jim@weirichhouse.org 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)

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

···

On Thu, 20 Jan 2005 00:19:13 +0900, David A. Black <dblack@wobblini.net> wrote:

What would you replace 5 with? :slight_smile:

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

lets please just end this with a simple word:
   performance
this thread has been repeated over and over again
i'd suggest reading the archives rather than
repeating it again.

florian has already suggested a possible solution,
i've suggested a very slow but 2 line solution,
and now its just degraded into the 'possibility'
to fix the hammer when the nail has disappeared
several messages back.

i agree for what its worth, its confusing at
first, but its *right* from a performance aspect
and *not wrong* in forcing you to rethink design.

Alex

···

On Jan 19, 2005, at 5:20 PM, Mohammad Khan wrote:

Here, I agree with you.
certain _types_ of object are (probably) : clonable and not clonable

Florian Gross wrote:

trans. wrote:

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.

No, other languages use other models that need this. They don't work like Ruby which is why they need it. Ruby needs other features that those languages don't have in certain cases, but over all I have to say that Ruby did a good job at being simple and consistent which is one of the top reasons I like it so much. Everything just makes sense once you understand the basics.

There's multiple approaches to this, but they should not be mixed.

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.

No, it can not be done. You can never modify a variable that appeared in your method invocation. You can change the Objects that you're methods gets in case they are value Objects, but that's how OOP works. It makes sense to be able to have entities that can change their state at run time.

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

Greetings,
Andreas

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.

Mark Hubbart wrote:

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.

Mohammad Khan wrote:

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.

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.

Which gets right back to the original question:

*Why* do you want to be able to do that? Is there not something else
that you can perhaps do to improve your design that doesn't require
this, since it's not really a supported mode of operation in Ruby?

-austin

···

On Thu, 20 Jan 2005 03:47:38 +0900, Mohammad Khan <mkhan@lextranet.com> wrote:

On Wed, 2005-01-19 at 13:41, Florian Gross wrote:
> Mohammad Khan wrote:
> > 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.
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)

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Jim Weirich wrote:

See http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc for
details on how to implement ref.

BTW, I think this actually inspired me to write Binding.of_caller and variable.rb. (Pretty much what you did in the article, but without the {} syntax.) Thanks a bunch for that great article. :slight_smile:

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

···

On Jan 19, 2005, at 4:38 PM, Michel Martens wrote:

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.

Hi --

···

On Thu, 20 Jan 2005, Michel Martens wrote:

On Thu, 20 Jan 2005 00:19:13 +0900, David A. Black <dblack@wobblini.net> wrote:

What would you replace 5 with? :slight_smile:

(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.

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
:slight_smile:

David

--
David A. Black
dblack@wobblini.net

Michel Martens wrote:

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.

Something is usually wrong when you want an Object to change classes at run time. There's certain use cases for this, but at large it's related to confusing variables with Objects.

E.g. if you expect the above to work you're likely to expect this:

a = /something/
b = a
a.replace "other"
a # => "other"
b # => /something/

But you can not have that. The last line will always result in "other" as well.

If you don't expect this and if you can live with quite some limitations you should have a look at the Object#become that evil-ruby implements. (See evil.rubyforge.org)

Andreas Semt wrote:

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

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

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

Can we all pretend that it didn't happen? :wink:

Mark Hubbart wrote:

> 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

Ah, I hadn't thought of that. I guess if you would need to
de-reference in conditionals:
  do_something if ref.__value__

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.

I didn't know of that one. So String.scan doesn't use duck typing?

Fifth:

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

I would consider that a feature :slight_smile: at a later time, a method could be
added, __ref__, would would allow you to call normal ruby methods on
the reference object; get its id, inspect it, etc.

This was really just a proof-of-concept... and you showed a couple of
big holes in it. :slight_smile: Ahh, well. I suspect that for most things, this
will work, with stated caveats.

cheers,
Mark

···

On Thu, 20 Jan 2005 04:16:02 +0900, Florian Gross <flgr@ccan.de> wrote: