简体   繁体   中英

Ruby - overriding/enabling multiple assignment (e.g. `a, b, c = d, e, f`)

In ruby, you can do this:

d = [1, 2, 3]
a, b, c = d

a , b , and c , will receive the values 1, 2, and 3, respectively.

d , in this case in an Array and ruby knows to assign it's contents to a , b , and c . But, if d were a Fixnum , for example, only a would be assigned to the value of d while b and c would be assigned nil .

What properties of d allow it to be used for multiple assignment? In my exploring so far, I've only been able to make instances of subclasses of Array behave in this way.

This is a very undocumented feature, and I'd use it with caution, but here we go. From the book The Ruby Programming Language:

When there are multiple lvalues and only a single rvalue, Ruby attempts to expand the rvalue into a list of values to assign. If the value is an array, Ruby expands the array so that each element becomes its own rvalue. If the value is not an array but implements a to_ary method, Ruby invokes that method and then expands the array it returns.

In Ruby 1.8 it is the to_ary method, in Ruby 1.9 documentation says it calls to_splat , but I haven't tested (no 1.9 in this machine) It didn't work as expected . So, you have to define a to_ary method in your object.

class Week
  def to_ary
    %w(monday tuesday wednesday thursday friday saturday sunday)
  end
end

mon, tue, wed, thu, *weekend = Week.new

* %w(...) Is a special notation for an array of words, if you are lazy to write ['monday', 'tuesday' ...]

What properties of d allow it to be used for multiple assignment?

d has to be an Array or be convertible to one. IOW it must be either an instance of the Array class (or any of its subclasses) or respond to the to_ary message:

def (not_an_array = Object.new).to_ary; [:foo, :bar, :baz] end

foo, bar, baz = not_an_array

foo # => :foo
bar # => :bar
baz # => :baz

Note that this is an instance of a more general pattern in Ruby: almost all methods in Ruby that expect an Array , a String , an Integer or a Float will also accept an object that responds to to_ary , to_str , to_int or to_float . And your own methods should, too, by the way!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM