Code syntax comma usage

That I can see; Pragmatic Programming Ruby’s, index, has reference to
all sorts of symbols, but I can’t find a explanation for a ‘,’ seperator
such as used in the following:

var1 = 1; p var1 #=> 1
var2 = 2; p var2 #=> 2
var3 = 3; p var3 #=> 3

var1, var2, var3 = 5

p var1 #=> 5
p var2 #=> nil
p var3 #=> nil

What’s happening here? I read it as:
set var1 to 5 and reset var2 and var3 to nil.
Is that all the comma does?

Jcm Mz wrote:

That I can see; Pragmatic Programming Ruby’s, index, has reference to
all sorts of symbols, but I can’t find a explanation for a ‘,’ seperator
such as used in the following:

var1 = 1; p var1 #=> 1
var2 = 2; p var2 #=> 2
var3 = 3; p var3 #=> 3

var1, var2, var3 = 5

p var1 #=> 5
p var2 #=> nil
p var3 #=> nil

What’s happening here? I read it as:
set var1 to 5 and reset var2 and var3 to nil.
Is that all the comma does?

Consider:

irb(main):005:0> a,b,c = 5,6,7
=> [5, 6, 7]

irb(main):006:0> a
=> 5

irb(main):007:0> b
=> 6

irb(main):008:0> c
=> 7

Multiple assignment from array parameters is very useful as well…

ra_parm = [1,2,3]

def meth(ra_parm)
p1, p2, p3 = ra
end

Regards

set var1 to 5 and reset var2 and var3 to nil.
Is that all the comma does?

It can be used for parallel assignments:

a,b,c = [1,2,3]
a #=> 1
b #=> 2
c #=> 3

When you enter “var1, var2, var3 = 5” in irb, you’ll get [5] as return
value. It seems the 5 gets silently converted into an array here.
Interesting.

Multiple assignment from array parameters is very useful as well…

ra_parm = [1,2,3]

def meth(ra_parm)
p1, p2, p3 = ra
end

Regards

Make that…

def meth(ra_parm)
p1, p2, p3 = ra_parm
end

Jcm Mz wrote:

That I can see; Pragmatic Programming Ruby’s, index, has reference to
all sorts of symbols, but I can’t find a explanation for a ‘,’ seperator
such as used in the following:

var1 = 1; p var1 #=> 1
var2 = 2; p var2 #=> 2
var3 = 3; p var3 #=> 3

var1, var2, var3 = 5

p var1 #=> 5
p var2 #=> nil
p var3 #=> nil

What’s happening here?

It’s called “parallel assignment”. Here is the basic case:

x, y = 10, 20
puts x #10
puts y #20

Then there are rules for dealing with the cases when the number of
variables on the left side do not equal the number of values on the
right side. You are seeing the rule: if there are more “lvalues” than
“rvalues”, the excess lvalues will have nil assigned to them.

One of the little tricks you can do with parallel assignment is switch
values in two variables without using a third variable:

str = “hello”
num = 100
str, num = num, str

puts str #100
puts num #hello

Normally, if there are more rvalues than lvalues then the excess rvalues
are discarded, for example:

x, y = 10, 20, 100, 200
puts x #10
puts y #20

But you can also do this:

x, y, *remaining = 10, 20, 100, 200

puts x #10
puts y #20
p remaining #[100, 200]

And this is also another way to do parallel assignment:

x, y, z = [10, 20, 30]
puts x #10
puts y #20
puts z #30

In pickaxe2, a detailed description of parallel assignment is on p. 340.

It seems the 5 gets silently converted into an array here.

The 5 doesn’t get converted of course and [5] is the value of the
assignment. At times, I find ruby’s permissiveness slightly
surprising.

Jcm Mz [email protected] wrote:

That I can see; Pragmatic Programming Ruby’s, index, has reference to
all sorts of symbols, but I can’t find a explanation for a ‘,’ seperator
such as used in the following:

var1, var2, var3 = 5

You’ve stumbled on one of Ruby’s most elegant bits of syntactical
niceness: multiple assignment. It isn’t the comma that’s interesting
here so much as the equal-sign and how it distributes assignments based
on lists. Try these:

arr = [1, 2, 3]

now look at what a, b, and c are after each of the following:

a, b, c = 1, 2, 3
a, b, c = [1, 2, 3]
a = b, c
a, b = b, a
a, b, c = arr
a, b, c = arr, 4
a, b, c = 4, arr
a, b, c = 4, *arr

m.

Hi –

On Sun, 15 Feb 2009, Tom L. wrote:

It seems the 5 gets silently converted into an array here.

The 5 doesn’t get converted of course and [5] is the value of the
assignment. At times, I find ruby’s permissiveness slightly
surprising.

That’s been fixed in 1.9, so that a,b,c = 5 returns 5.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

Jeff M. wrote:

Make that…

def meth(ra_parm)
p1, p2, p3 = ra_parm
end

Don’t you need a splat for that?

def meth(ra_parm)
p1, p2, p3 = *ra_parm
end

Tom L. wrote:

When you enter “var1, var2, var3 = 5” in irb, you’ll get [5] as return
value. It seems the 5 gets silently converted into an array here.
Interesting.

The 5 doesn’t get converted of course and [5] is the value of the
assignment. At times, I find ruby’s permissiveness slightly
surprising.

The value of the assignment is written as 5, so if you end up with [5]
then it seems logical that something got converted.

Hi –

On Sun, 15 Feb 2009, David M. wrote:

def meth(ra_parm)
p1, p2, p3 = *ra_parm
end

No. If ra_parm is an array, it will assign in parallel to the
variables on the left.

irb(main):010:0> a,b,c = [1,2,3]
=> [1, 2, 3]
irb(main):011:0> a
=> 1
irb(main):012:0> b
=> 2
irb(main):013:0> c
=> 3

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

David M. wrote:

Jeff M. wrote:

Make that…

def meth(ra_parm)
p1, p2, p3 = ra_parm
end

Don’t you need a splat for that?

def meth(ra_parm)
p1, p2, p3 = *ra_parm
end

  1. You could test that yourself in less than 30 seconds.

  2. You could actually read the thread and discover the answer: there
    are two posts containing the answer.

Jcm Mz wrote:

What’s happening here? I read it as:
set var1 to 5 and reset var2 and var3 to nil.
Is that all the comma does?

The answer I was looking for was in fact the multiple assignment comma
operation.

The original code I was looking at was:

class Timer
private
def dispatch
now = Time.now.to_f
ready, @queue = @queue.partition{|time, proc| time <= now }
ready.each {|time, proc| proc.call((time)}
end
end

p24 Practical Ruby Projects