[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

what is *self?

josefK

11/22/2006 8:17:00 PM

I encountered this added method to Array (I don't recall
the author - sorry ,)
It converts an Array to a Hash by providing a block to compute the
values given the array elements as keys:



class Array
def to_h(&block)
Hash[*self.collect{|v| [v,block.call(v)]}.flatten]
end
end


#exp
a=[1,2,3]
h=a.to_h{|e| 2**e}
h.each{|k,v| puts "key=#{k} val=#{v}"}

#->key=1 val=2 key=2 val=4 key=3 val=8




Without the '*' on self it generates an error:
array2hash.rb:3:in `[]': odd number of arguments for Hash (ArgumentError)
from array2hash.rb:3:in `to_h'
from array2hash.rb:8


What does the '*' do to correct the error?

Does it push self up a level to Array somehow?

Does this notation generalize?



Thanks,

Mark
3 Answers

Vidar Hokstad

11/22/2006 8:56:00 PM

0


josefK wrote:
> I encountered this added method to Array (I don't recall
> the author - sorry ,)
> It converts an Array to a Hash by providing a block to compute the
> values given the array elements as keys:
>
> class Array
> def to_h(&block)
> Hash[*self.collect{|v| [v,block.call(v)]}.flatten]
> end
> end
>

"*" is the "splat" operator when used as a prefix. It takes the
following array, and turns into a list of parameters. Without it the
argument to Hash[] becomes a single Array, while it expects a list of
keys and values.

And yes, it does generalize. Try
p [1,2,3]
p *[1,2,3]
in irb to get a better idea of the result. The first prints a single
array, the second prints _three separate values_

Vidar

josefK

11/22/2006 9:38:00 PM

0

Vidar Hokstad wrote:

> josefK wrote:
>
>>I encountered this added method to Array (I don't recall
>>the author - sorry ,)
>>It converts an Array to a Hash by providing a block to compute the
>>values given the array elements as keys:
>>
>>class Array
>> def to_h(&block)
>> Hash[*self.collect{|v| [v,block.call(v)]}.flatten]
>> end
>>end
>>
>
>
> "*" is the "splat" operator when used as a prefix. It takes the
> following array, and turns into a list of parameters. Without it the
> argument to Hash[] becomes a single Array, while it expects a list of
> keys and values.
>
> And yes, it does generalize. Try
> p [1,2,3]
> p *[1,2,3]
> in irb to get a better idea of the result. The first prints a single
> array, the second prints _three separate values_
>
> Vidar
>


OK - I see - it does not affect 'self' just the output []
I thought it was a way to modify 'self'

I guess 'super' and 'super.super...' is the generalization
I mistakenly thought was happening.

Thanks much,


Mark

Jacob Fugal

11/24/2006 9:04:00 PM

0

On 11/24/06, josefK <josefK@kafka.org> wrote:
> I encountered this added method to Array (I don't recall
> the author - sorry ,)
> It converts an Array to a Hash by providing a block to compute the
> values given the array elements as keys:
>
> class Array
> def to_h(&block)
> Hash[*self.collect{|v| [v,block.call(v)]}.flatten]
> end
> end

Vidar explained the general concept of the splat fairly well, but the
following clarification of order of operations should help understand
this particular application:

# assuming self = [ 1, 2, 3 ] and block = proc{ |x| x**2 }
self.
collect{|v| [v,block.call(v)]}. # => [[1, 1], [2, 4], [3, 9]]
flatten # => [1, 1, 2, 4, 3, 9]

Without the star, the full Method body would be (equivalently):

Hash[[1, 1, 2, 4, 3, 9]]

This complains about an odd number of elements because it's receiving
only one element -- the array. Adding the "splat" in essence removes
the innermost pair of square brackets:

Hash[1, 1, 2, 4, 3, 9]

Hash#[] can then use the list as key/value pairs.

As I said, Vidar explained the operation of the splat well, I just
wanted to point out *which* array the star was operating on -- the
result of the expression "self.collect{ ... }.flatten", not to self
itself (no pun intended).

Jacob Fugal