How to get real reference to an object?

Assume a big hash and/or a nested structure and the need of a plenty of
operations on some hash[…][…][…] which is Float. How can one avoid
the repetitious evaluation of the indices? I have not been able to get a
“real” reference to that variable to do something_like tmp =
referenceof(hash[…][…][…]) and work with the value directly
through the (dereferenced) tmp variable. In Perl I would say

$ perl -e ‘$x[1][2][3] = 1; $a = $x[1][2][3]; $$a = 3; print
$x[1][2][3]’
3

(where … is a reference and $ before $a is a dereference).

Morover, why the return value of the assignment is not an l-value? The
following is legal in Perl ($x ||= 1) *= 2 — why it is not legal in
Ruby as well?

Thanks, P.

Hi –

On Thu, 23 Jul 2009, Pavel S. wrote:

(where … is a reference and $ before $a is a dereference).
h = { :a => { :b => {} } }
tmp = h[:a][:b]
tmp[:x] = “hi”
tmp[:x] << " there"
p h # => {:a=>{:b=>{:x=>“hi there”}}}

You’re (almost) always dealing in references in Ruby. (And the almost
part doesn’t affect you much anyway.) Every reference is exactly one
step away from the object; there’s no such thing as a reference to a
reference. It’s very different from Perl in that respect.

Morover, why the return value of the assignment is not an l-value? The
following is legal in Perl ($x ||= 1) *= 2 — why it is not legal in Ruby as
well?

I assume it’s because (x ||= 1) evaluates to the object 1, and 1 *= 2
doesn’t make sense.

David

Pavel S. schrieb:

(where … is a reference and $ before $a is a dereference).

Morover, why the return value of the assignment is not an l-value? The
following is legal in Perl ($x ||= 1) *= 2 — why it is not legal in
Ruby as well?

Thanks, P.

You can’t get references of immediate values like Fixnums or Symbols. If
you want a reference, the only way you could do is to get a reference to
the innermost Hash:

irb(main):001:0> hsh = {1 => {2 => {3 => :value}}}
=> {1=>{2=>{3=>:value}}}
irb(main):002:0> hsh[1][2][3]
=> :value
irb(main):003:0> ref = hsh[1][2]
=> {3=>:value}
irb(main):004:0> ref[3] = :xyz
=> :xyz
irb(main):005:0> ref[3]
=> :xyz
irb(main):006:0> hsh[1][2][3]
=> :xyz

Morover, why the return value of the assignment is not an l-value? The
following is legal in Perl ($x ||= 1) *= 2 — why it is not legal in
Ruby as well?
You try to assign a value to a Fixnum. The result of $x ||= 1 is 1 (if
$x is unintitialized) and so your expression would evolve to:
1 = 1 * 2
which is invalid code.

Marvin

David A. Black wrote:

(where … is a reference and $ before $a is a dereference).

h = { :a => { :b => {} } }
tmp = h[:a][:b]
tmp[:x] = “hi”
tmp[:x] << " there"
p h # => {:a=>{:b=>{:x=>“hi there”}}}

Yes, but I need something like:

$ ruby -e ‘h = { :a => { :b => “hi” } }; tmp = h[:a][:b]; tmp << "
there"; p h’
{:a=>{:b=>“hi there”}}

which is OK, but not for Float:

$ ruby -e ‘h = { :a => { :b => 5.0 } }; tmp = h[:a][:b]; tmp += 5.0; p
h’
{:a=>{:b=>5.0}}

And that’s why I’m asking for a “real” reference, because tmp apparently
is not any kind of reference to the h[:a][:b].

You’re (almost) always dealing in references in Ruby. (And the almost
part doesn’t affect you much anyway.) Every reference is exactly one
step away from the object; there’s no such thing as a reference to a
reference. It’s very different from Perl in that respect.

Mhm, an unfortunate difference, I’m afraid…

Of course, I could write tmp = h[:a] and then many times tmp[:b]. But
something like simple tmp as in Perl would seem to me far more elegant.

Morover, why the return value of the assignment is not an l-value? The
following is legal in Perl ($x ||= 1) *= 2 — why it is not legal in Ruby as
well?

I assume it’s because (x ||= 1) evaluates to the object 1, and 1 *= 2
doesn’t make sense.

I know, my question is, why it does not evaluate to x. Then it would
have the same value (the value of x) and moreover it could stand on the
left side of an another assignment (as the x *= 2 does make sense).

Thanks, P.

On Jul 23, 2009, at 10:25 AM, Pavel S. wrote:

$ perl -e '$x[1][2][3] = 1; $a = $x[1][2][3]; $$a = 3; print $x[1]
Yes, but I need something like:

And that’s why I’m asking for a “real” reference, because tmp
apparently is not any kind of reference to the h[:a][:b].

Well, it is, but Fixnum’s are immediate (implementation detail) and
Float’s act like value objects. What would happen if:
5.0 += 5.0
were legal? All 5’s now act like 10’s??

Thanks, P.

Because in Ruby, “x.y = z” is just syntactic sugar when x is an object
for:
x.send(:y=, z)
with the rule that the “value” of an assignment is the right-hand side
(i.e., z) so things like
w = x.y = z
are predictable (meaning that the “y=” method sent to x can’t return
something other than z for the assignment to w. (And, the rule breaks
down if you don’t use the sugar, but make the calls yourself:
w = x.send(:y=, z)
might result in w != z, but any programmer that does such a thing in
“real” code should be punished.)

-Rob

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

On Jul 23, 2009, at 10:25 AM, Pavel S. wrote:

The following is legal in Perl ($x ||= 1) *= 2 — why it is not
legal in Ruby as well?
I assume it’s because (x ||= 1) evaluates to the object 1, and 1 *= 2
doesn’t make sense.

I know, my question is, why it does not evaluate to x. Then it would
have the same value (the value of x) and moreover it could stand on
the left side of an another assignment (as the x *= 2 does make
sense).

It doesn’t evaluate to x because Ruby isn’t Perl. It isn’t like there
is an absolute right or wrong way to design a language. Each language
has its own idioms and techniques, some of which are not translatable
from one language to the next.

And that’s why I’m asking for a “real” reference, because tmp
apparently is not any kind of reference to the h[:a][:b].

Variables in Ruby hold references to objects. They are not labels for
memory where values are stored. Your example should be written as:

h[:a][:b] += 5.0

Gary W.

Hi –

On Thu, 23 Jul 2009, Pavel S. wrote:

3

not any kind of reference to the h[:a][:b].
Right; I wasn’t taking into account the fact that your example was
dealing with numbers.

You’re (almost) always dealing in references in Ruby. (And the almost
part doesn’t affect you much anyway.) Every reference is exactly one
step away from the object; there’s no such thing as a reference to a
reference. It’s very different from Perl in that respect.

Mhm, an unfortunate difference, I’m afraid…

You’ll have to talk to Larry about fixing it :slight_smile: Seriously though… I
would advise you strongly not to compare Ruby and Perl token-by-token
or construct-by-construct. It’s like criticizing a flute because it
doesn’t have strings.

Of course, I could write tmp = h[:a] and then many times tmp[:b]. But
something like simple tmp as in Perl would seem to me far more elegant.

The two languages have completely different variable and assignment
semantics. Again, I’d try to get to know Ruby on its own terms.
There’s plenty of elegance to be had there :slight_smile:

David