Ruby expressions vs. values (like Perl?)

Does Ruby use the same terminology as Perl with regard to expressions
versus values?

I read a great MJD comment on PerlMonks a while back (
http://www.perlmonks.org/?node_id=72263 ). That comment notes how, in
Perl, one needs to be well aware of the difference between expressions
(the things you type into your code), and values (the things the
interpreter evaluates expressions to).

It seems that, the big reason for watching the difference between
expressions and values in Perl is because expressions turn into
different values at runtime depending upon context.

So, back to Ruby, I believe that the rhs of the following statement is
an “Array expression”:

irb(main):001:0> foo = [‘a’,‘bee’,‘sea’]
=> [“a”, “bee”, “sea”]

but, what kind of expression is the rhs of the following:

irb(main):002:0> bar = ‘dee’, ‘ee’, ‘eff’
=> [“dee”, “ee”, “eff”]

?

Incidentally, I also note that this one – although performing
parallel assignment – also happens to be generating an Array value:

irb(main):003:0> zz = ( a, b, c = ‘gee’, ‘aitch’, ‘aye’ )
=> [“gee”, “aitch”, “aye”]

irb(main):004:0> zz
=> [“gee”, “aitch”, “aye”]

According to irb, the Array gets generated even if you leave off the
“zz =” and the parentheses. Seems like extra work for the interpreter
to go through (making that Array), just to do a parallel assignment,
no?

Thanks,
—John

-----BEGIN PGP SIGNED MESSAGE-----

In article
[email protected],
John G. [email protected] wrote:

expressions and values in Perl is because expressions turn into
different values at runtime depending upon context.

This is what many people dislike about perl. In Ruby, the
distinction mostly doesn’t exist. It’s an Object…

=> [“dee”, “ee”, “eff”]

?

One of the nice things about Ruby is that you can always ask it
what it thinks.

irb(main):090: bar.class
=> Array
irb(main):010:0> bar.methods
=> [“respond_to?”, “index”, “select”, “<<”, “to_a”, “delete_if”,
“slice”, “&”, “type”, “each_index”, “length”,
“protected_methods”, “partition”, “sort!”, “assoc”, “to_ary”,
“eql?”, “*”, “grep”, “instance_variable_set”, “+”, “is_a?”,
“hash”, “push”, “send”, “to_s”, “-”, “rindex”, “reject”, “size”,
“pack”, “join”, “class”, “reverse_each”, “tainted?”, “collect!”,
“private_methods”, “rassoc”, “at”, “member?”, “send”,
“compact!”, “untaint”, “|”, “find”, “each_with_index”, “reject!”,
“flatten”, “id”, “pop”, “slice!”, “replace”, “collect”,
“inspect”, “transpose”, “instance_eval”, “reverse”, “all?”,
“clone”, “entries”, “indexes”, “public_methods”, “map!”, “uniq”,
“fetch”, “extend”, “freeze”, “detect”, “values_at”, “display”,
“zip”, “id”, “shift”, “<=>”, “methods”, “method”, “map”,
“==”, “clear”, “empty?”, “===”, “any?”, “indices”, “sort”,
“nil?”, “dup”, “instance_variables”, “include?”, “min”,
“instance_of?”, “flatten!”, “first”, “find_all”, “delete_at”,
“nitems”, “each”, “object_id”, “insert”, “reverse!”, “unshift”,
“=~”, “inject”, “singleton_methods”, “fill”, “delete”, “concat”,
“uniq!”, “equal?”, “taint”, “sort_by”, “instance_variable_get”,
“max”, “[]”, “frozen?”, “compact”, “kind_of?”, “last”, “[]=”]

According to irb, the Array gets generated even if you leave off the
“zz =” and the parentheses. Seems like extra work for the interpreter
to go through (making that Array), just to do a parallel assignment,
no?

It’s not making an Array, it’s making a reference to an existing
object. Every ruby statement generally returns a reference
to the result, this can be an incredibly powerful tool.

_ Booker C. Bense

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBRS7BCGTWTAjn5N/lAQGrXgP+NWJ+xN04v1o67cQ9PSQeHCtakRJQAz3r
Rx/ivNqUXXMeR9uL3G2Ffui8BTE1KGpnsci2rzBcrxn2w1yjqAOV/IkmKFrmk72g
27FlxtqVCT3OonCx1KtsHF/8akrqlojFPwdw5MVvDXAxFQoYYOY2DE17WVmfXmY9
T+wBUTromgw=
=Ilxn
-----END PGP SIGNATURE-----

On 10/12/06, Booker C. Bense
[email protected] wrote:

but, what kind of expression is the rhs of the following:
=> Array
irb(main):010:0> bar.methods
=> [“respond_to?”, “index”, “select”, “<<”, “to_a”, “delete_if”,
“slice”, “&”, “type”, “each_index”, “length”,
[snip]

Right. I see that bar is an Array, but I what I meant was, what kind
of expression is that comma-separated thingy on the right hand side
(when I made the assignment to bar)? Evidently, the answer seems to be
that ruby is allowing a little bit of extra syntactic sugar to make it
so I don’t have to type those square brackets.

According to irb, the Array gets generated even if you leave off the
“zz =” and the parentheses. Seems like extra work for the interpreter
to go through (making that Array), just to do a parallel assignment,
no?

It’s not making an Array, it’s making a reference to an existing
object.

Huh? irb seems to be clearly showing an Array. I’m thinking it’s like
in C++ where you have this little short-lived temporary object. It
seems like it’s an extra step for the interpreter to bother making
that extra temporary – I’d think it could’ve just done the assignment
to a, b, and c and be done with it.

—John

-----BEGIN PGP SIGNED MESSAGE-----

In article
[email protected],
John G. [email protected] wrote:

of expression is that comma-separated thingy on the right hand side
(when I made the assignment to bar)? Evidently, the answer seems to be
that ruby is allowing a little bit of extra syntactic sugar to make it
so I don’t have to type those square brackets.

Yes. For good or ill, Ruby has various syntactic sugar bits
sprinkled about.

object.

Huh? irb seems to be clearly showing an Array. I’m thinking it’s like
in C++ where you have this little short-lived temporary object. It
seems like it’s an extra step for the interpreter to bother making
that extra temporary – I’d think it could’ve just done the assignment
to a, b, and c and be done with it.

This is the part of Ruby that took me the longest to get my head
around and I think causes lot’s of difficulties since it uses a
reference model that’s quite different from many other languages.
Variables are always a reference to an object, assignment copies
the reference but not the object. In many languages you can do

a = b

and then manipulate a , but b will remain unchanged. In Ruby,
both b and a are pointers to the underlying object and if you
change a then b changes as well. There is only 1 Array object
in the fragment above. In Ruby if you want a more conventional
version of assignment you do

a = b.copy

_ Booker C. Bense

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBRS+f7GTWTAjn5N/lAQEjEgP+IWgJY5cyaJOb1Xp1I7t0kJulonMPuqKY
Vj9wXYNgS05jKuGz0xRY8EVcMHopJxELn0+Zij0cknAYeEkSn+Balnnw3kJk+5oi
Ao6w/9nK1eRZ4tOFcXBMqHyMedHlavKXBm+BIIJDJHH9COTJkFB/0lN/qRkCc7cE
Ovaey9QPQhs=
=vY74
-----END PGP SIGNATURE-----

John G. wrote:

=> [“a”, “bee”, “sea”]

that ruby is allowing a little bit of extra syntactic sugar to make it

=> [“gee”, “aitch”, “aye”]
in C++ where you have this little short-lived temporary object. It
seems like it’s an extra step for the interpreter to bother making
that extra temporary – I’d think it could’ve just done the assignment
to a, b, and c and be done with it.

—John

Someone with better understanding of Ruby internals will need to
confirm this because I may well be wrong, but I think you are correct.
eval.c creates a temporary array out of the right-hand side (in the
svalue_to_mrhs function I think). Page 91 of the Pickaxe (2nd Ed)
explains this a little more. Whether or not optimising the Array away
is possible or desirable is another question. Unless you are doing some
pretty insane parallel assignment I wouldn’t have thought it makes any
practical difference.

Alex G.

On 10/12/06, AlexG [email protected] wrote:

Someone with better understanding of Ruby internals will need to
confirm this because I may well be wrong, but I think you are correct.
eval.c creates a temporary array out of the right-hand side (in the
svalue_to_mrhs function I think). Page 91 of the Pickaxe (2nd Ed)
explains this a little more. Whether or not optimising the Array away
is possible or desirable is another question. Unless you are doing some
pretty insane parallel assignment I wouldn’t have thought it makes any
practical difference.

Yep, that’s exactly what seems to be happening.

One reason for this is so that a parallel assignment like

 x, y = y, x

works correctly.

If the interpreter simply broke that down into series of assignments
without the temporary array, then it would need to detect such cases
and handle them separately or:

x = 1
y = 2

x, y = y, x

converted into

x = y
y = x

x => 2
y => 2

which is not what we want.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/

On 10/13/06, Rick DeNatale [email protected] wrote:

y = 2

x, y = y, x

converted into

x = y
y = x

x => 2
y => 2

which is not what we want.

Ah. Of course. Thanks.

Also, to answer my own original question, I think actually that it may
not’ve had much pith to it… That is to say, everything the
interpreter sees is an “expression” of some kind (regardless of the
name one wants to give that expression). I think, most of the time,
ruby simply turns expressions into what values you think they should
be turned into, and (as Booker mentions) sprinkles little syntactic
sugar bits around here and there for the programmer’s convenience.

Perl does the same thing, except it has some arguably quirkier rules
about the values it thinks the expressions should be evaluated to.

Thanks,
—John