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
(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?
(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.
(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:
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.
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).
$ 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.)
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:
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 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
David
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.