Variable pointer

@c = “donal”
@b = @c

abrakadabra(@b, @c)

@c = “mickey”

print @b resulted “mickey”

Is there something like abrakadabra method in ruby? The only thing I
can think to emulate this is using global variable.

Thank you.

On 11/1/06, akbarhome [email protected] wrote:

can think to emulate this is using global variable.
No. Variables aren’t pointers or locations; they’re labels for
objects. By changing @c you have changed its object. You haven’t
changed @c.

However, you can trick it out with a Var (or Ref) object (google
around for various implementations) where you can set the value,
something like:

c = Ref.new(“donald”)
b = c
c._value = “mickey”
puts b

-austin

HI –

On Wed, 1 Nov 2006, akbarhome wrote:

can think to emulate this is using global variable.
It was recently noted on the Rails mailing list that something like
that happens in ActiveRecord. Given Person and Address models, where
Person has_one Address:

a = person.address
person.address = Address.find(some_other_address)
puts a # a has changed!

I find it un-Rubyish and disconcerting (though I’m still waiting for
someone to explain the rationale; there may be something I’m missing).

I think you have to work pretty hard to get that to happen. Now and
then there’s a vogue for “become”, which might do something like this
(i.e., change all references), though not with assignment syntax.

David

On Thu, 2 Nov 2006 [email protected] wrote:

It was recently noted on the Rails mailing list that something like
that happens in ActiveRecord. Given Person and Address models, where
Person has_one Address:

a = person.address
person.address = Address.find(some_other_address)
puts a # a has changed!

I find it un-Rubyish and disconcerting (though I’m still waiting for
someone to explain the rationale; there may be something I’m missing).

can you show an example? are you saying that activerecord avoids
apparent
copy-on-write semantics with some trickery?

-a

akbarhome ([email protected])
1/11/2006 16:45:17

@c = “donal”
@b = @c

abrakadabra(@b, @c)

@c = “mickey”
^^^^ the problem is here

In ruby, var = value is not “change var’s value”, but rather “set name
var for value”.
Then, after
@b = @c
@c and @b “points” to same value, and if you change this value, you
would see new value through @b and through @c.

@c = “donal”
@b = @c
@c.upcase!
print @b #=> DONAL

but when you do
@c = “mickey”

@c becames to ‘point’ to “mickey”, and @b - still to “donal”.
AFAIK, there’s no way to change @b in correspondence.

V.

Hi –

On Thu, 2 Nov 2006, [email protected] wrote:

I find it un-Rubyish and disconcerting (though I’m still waiting for
someone to explain the rationale; there may be something I’m missing).

can you show an example? are you saying that activerecord avoids apparent
copy-on-write semantics with some trickery?

Here’s an example from a program which models Ideas; each Idea belongs
to a Page.

i = Idea.find(6)
=> #<Idea:0xb79eec2c @attributes={“page_id”=>“6”, “id”=>“6”,
“content”=>“Go to Paris”}>

Save the idea’s page in p

p = i.page
=> #<Page:0xb79e4a88 @attributes={“scratchpad_id”=>“6”,
“title”=>“Domestic travel”, “id”=>“6”}>

Change the idea’s page to a different one

i.page = Page.find(7)
=> #<Page:0xb79d1b18 @attributes={“scratchpad_id”=>“1”,
“title”=>“Foreign travel”, “id”=>“7”}>

Examine the saved page – it’s the new one

p
=> #<Page:0xb79d1b18 @attributes={“scratchpad_id”=>“1”,
“title”=>“Foreign travel”, “id”=>“7”}>

I don’t know the rationale. When I (think I’m) assign(ing) an object
to a variable, I really don’t want it to turn out that it’s some
special arrangement whereby the variable is subject to reassignment
without notice. I expect:

p = i.page

to be exactly equivalent to:

p = Idea.find(i.page.id)

with respect to p.

David

On Thu, 2 Nov 2006 [email protected] wrote:

with respect to p.

holy cow that is pure evil!

thanks for the example david.

-a

On 11/1/06, [email protected] [email protected] wrote:

a = person.address
to a Page.

Change the idea’s page to a different one

to a variable, I really don’t want it to turn out that it’s some

I must be missing something. Isn’t this how virtually all Ruby code
works?

class Foo
attr_accessor :bar
end

f = Foo.new
f.bar = “some_string”

p = f.bar
f.bar << " and how!"
puts p

What makes the Rails version of this unexpected?

On Nov 1, 2006, at 10:07 AM, Wilson B. wrote:

f.bar << " and how!"

Change that line to:

f.bar = “new string”

James Edward G. II

Hi –

On Thu, 2 Nov 2006, Wilson B. wrote:

“title”=>“Domestic travel”, “id”=>“6”}>

f.bar = “some_string”

p = f.bar
f.bar << " and how!"
puts p

What makes the Rails version of this unexpected?

I’m not modifying an object in place, though; I’m doing a new
assignment. Or at least that’s what it appears to be:

i.page = Page.find(7)

So it’s more like:

a = “str”
b = a
a = “new str”
puts b # new str

I (strongly) believe that the assignment-like syntax should not be
rigged to do this.

David

On 11/1/06, [email protected] [email protected] wrote:

a = person.address
to a Page.

Change the idea’s page to a different one

to a variable, I really don’t want it to turn out that it’s some

Wow, that looks nasty. Can you point me to the releveant thread in
the rails group where this was discussed?

  • Rob

On 2006-11-01, [email protected] [email protected] wrote:

“title”=>“Domestic travel”, “id”=>“6”}>

Change the idea’s page to a different one

i.page = Page.find(7)
=> #<Page:0xb79d1b18 @attributes={“scratchpad_id”=>“1”,
“title”=>“Foreign travel”, “id”=>“7”}>

Examine the saved page – it’s the new one

p
=> #<Page:0xb79d1b18 @attributes={“scratchpad_id”=>“1”,
“title”=>“Foreign travel”, “id”=>“7”}>

Yikes! How is this even possible? Somehow the method is changing the
variable bindings in its caller. Is this related to Binding.of_caller
(which exploited a bug in 1.8.4 and broke when the bug was fixed in
1.8.5 - see
URL:http://eigenclass.org/hiki.rb?breakpoint+breaking+in+1.8.5)?

Jeremy H.

On Nov 2, 2006, at 8:55 AM, Rob S. wrote:

where

“content”=>“Go to Paris”}>

p = i.page

  • Rob


http://www.robsanheim.com
http://www.seekingalpha.com
http://www.ajaxian.com

Why is this so hard to understand? Rails isn’t really doing anything
magic or really even tricky here – just “unexpected”.

You are just confusing references and objects.

require ‘ostruct’
=> true
o = OpenStruct.new(‘page’ => “original”, ‘cover’ => “hard”)
=> #<OpenStruct cover=“hard”, page=“original”>
p = o.page
=> “original”

No surprise there. Let’s change the contents of the page.

o.page.replace(“forgery”)
=> “forgery”

…and check in with our variable (aka, object reference):

p
=> “forgery”

Yup. Still refers to the same String object as o.page. Now let’s do
an assignment:

o.page = “restoration”
=> “restoration”
p
=> “forgery”

o.page now refers to a new object. But o.page = “restoration” is
really just sugar for o.page=(“restoration”), right?

def o.page=(kind); self.page.replace(kind); end
=> nil

Make p refer to the same String object as o.page again:

p = o.page
=> “restoration”
p
=> “restoration”
o.page
=> “restoration”

Now this “assignment” calls the newly defined page= method:

o.page = “imitation”
=> “imitation”
p
=> “imitation”
p.replace(“faux”)
=> “faux”
o.page
=> “faux”

So the way that variables are references to objects and the syntactic
sugar that makes ‘o.page = foo’ look like assignment even though it’s
sending foo to the page= method of the o object are just colliding in
your brain.

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Hi –

On Thu, 2 Nov 2006, Rob B. wrote:

Why is this so hard to understand? Rails isn’t really doing anything magic
or really even tricky here – just “unexpected”.

You are just confusing references and objects.

No, that’s not what’s going on. ActiveRecord is doing something quite
tricky.

=> “forgery”
There’s nothing analogous to this in the ActiveRecord example.

p
=> “forgery”

o.page now refers to a new object. But o.page = “restoration” is really just
sugar for o.page=(“restoration”), right?

That’s where ActiveRecord, in the equivalent operation, does something
very different. Imagine that when you examined p, you got
“restoration”. That would be the same as was AR is doing.

=> “restoration”
=> “faux”

So the way that variables are references to objects and the syntactic sugar
that makes ‘o.page = foo’ look like assignment even though it’s sending foo
to the page= method of the o object are just colliding in your brain.

I’m not sure why you have to express this in terms of confusion on the
part of the people who don’t like it. I think we’re all well aware of
=-terminated methods and all the rest of it. So let’s leave the
editorials about people’s brains out of it.

Anyway… No one is saying that you can’t do this in Ruby, only
that what AR does is unexpected, unidiomatic, and inconsistent. The
= syntactic sugar does, indeed, allow you to write arbitrary methods:

class C
def thing=(n)
puts “Ha ha!”
end
end

but the reason the sugar exists is to make assignment-like things look
like assignments. The thing that AR does is not assignment-like, in
any traditional or idiomatic sense. Yes, you can do a
non-assignment-based operation (like String#replace) in a =-method…
but, at the risk of sounding old-fashioned, I simply think that here:

old_thing = obj.thing
obj.thing = Thing.create

it’s reasonable to expect old_thing to refer to the original
obj.thing, and not the new one. In ActiveRecord, that’s not what
happens.

It’s not an object-vs.-reference thing, either. There’s a class
called ActiveRecord::Associations::AssociationProxy which, I believe,
is responsible for the way this works. old_thing is a proxy to
obj.thing. If you assign it differently:

old_thing = Thing.find(obj.thing.id)
obj.thing = Thing.create

old_thing does not change, because the proxy class is not involved.
All of this is on top of the usual object/reference stuff in Ruby; in
fact, it’s a kind of super-reference that’s being created (which is
precisely not the model that Ruby is built on – pointers to
pointers, so to speak – though as I’ve said the issue is not whether
or not it can be done).

As I’ve said before, if there’s a rationale for AR doing it the way it
does (other than the fact that it’s possible to do it that way, which
I doubt is what lies behind it), I would of course be very interested
in hearing it.

David

Hi –

On Thu, 2 Nov 2006, Rob S. wrote:

Wow, that looks nasty. Can you point me to the releveant thread in
the rails group where this was discussed?

It’s called: belongs_to nonintuitive results with assignment?

David

On 11/2/06, Rob B. [email protected] wrote:

=> “original”

def o.page=(kind); self.page.replace(kind); end
=> nil

This is the issue. I understand how assignment methods work, really I
do =). I just don’t see a reason for this and would assume the
implementation is the simplest thing unless we really need to change
that object in place. I would normally think this is just an
assignment, unless there were good optimization reasons to do
otherwise.

def o.page=(str); self.page = str; end

or more typically w/i the class def somewhere

attr_accessor :page
def initialize
@page = nil
end

Not sure why Rails would do an .replace instead, but maybe there are
good performance reasons relating to ActiveRecord…

  • Rob

Wilson B. [email protected] wrote:

On Thu, 2 Nov 2006 [email protected] wrote:

a = person.address
person.address = Address.find(some_other_address)
puts a # a has changed!

I must be missing something. Isn’t this how virtually all Ruby code works?

I had to do a double-take as well, so here’s an example for the rest of
us newbies trying to follow the discussion.

Presume the following:

address = Struct.new(:street).new(“Main”)
address2 = Struct.new(:street).new(“Oak”)
person = Struct.new(:address).new(address)

Okay, now let’s execute exactly the code being discussed:

[1]

a = person.address
person.address = address2
p a # Main

So assigning directly to person’s address didn’t change “a”.

OTOH:

[2]

a = person.address
person.address.street = “Oak”
puts a.street # => Oak

So I think what’s unexpected is that, in the RoR example, [1] behaves as
if it had been [2]. m.