From: Brian Candler Date: 2008-09-24T16:47:54+09:00 Subject: Re: understanding inheritance and class singleton methods > (or for that matter, specifications how 'splat' behaves > and the '&' operator before blocks) Splat turns an array into an argument list, or vice versa. def test1(*args) p args end test1(1,2,3) # prints the array [1, 2, 3] def test2(a, b, c) p a, b, c end arg2 = [4,5,6] test2(*arg2) # prints 4 then 5 then 6 You can use splat to "mop up" remaining arguments: def test3(a, b, *rest) p a, b, rest end test3(7, 8) # prints 7 then 8 then [] test3(7, 8, 9) # prints 7 then 8 then [9] You can also use it for multiple assignments: a, b = *[10, 11] and you can use it in blocks: foo { |x,*y| ... } Where it gets confusing is special "autosplat" magic which happens for multiple assignments and blocks where one side is a single array. a, b = [10, 11] p a, b # [10, 11] foo = 12, 13, 14 p foo # [12, 13, 14] arr = [ ["foo",1], ["bar",2], ["baz",3] ] arr.each { |x,y| p x, y } p arr.inject(0) { |accum,(k,v)| accum + k.length + v } Fortunately, autosplat doesn't happen for method calls, AFAIK. See http://innig.net/software/ruby/closures-in-ruby.rb (section 4) for more info. As for the & operator, this is pretty simple. It's just a way of turning the "hidden" block argument into a concrete argument. The following two are equivalent: def doit1(x,y) yield x+y end def doit2(x,y,&blk) blk.call(x+y) end Conversely, if you have an existing proc/lambda type of object, you can pass it instead of an inline block: arr = ["foo", "bar"] arr.each { |elem| puts "hello #{elem}" } callback = lambda { |elem| puts "hello #{elem}" } arr.each(&callback) And hence the blk itself can be passed around as an object. So: def doit3(arr) arr.each { |elem| yield elem } end becomes simply def doit4(arr,&blk) arr.each(&blk) end Personally, I found blocks and yield much easier to understand once I saw they were just passing a function as an extra argument, and calling that argument. -- Posted via http://www.ruby-forum.com/.