Ruby expressions vs. values (like Perl?)

J

John Gabriele

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
 
B

Booker C. Bense

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

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.

This is what many people dislike about perl. In Ruby, the
distinction mostly doesn't exist. It's an Object...
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"]

?

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", "[]="]

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?

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

John Gabriele

John Gabriele said:
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"]

?

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",
[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.
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?

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
 
A

AlexG

John said:
John Gabriele said:
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"]

?

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",
[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.
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?

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

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 Gutteridge
 
B

Booker C. Bense

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

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.

Yes. For good or ill, Ruby has various syntactic sugar bits
sprinkled about.
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"]

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.

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

Rick DeNatale

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/
 
J

John Gabriele

[snip]

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,170
Latest member
Andrew1609
Top