2012-08-23 15 views
5

Klammerung in Blockvariablen

Gegeben
a = [[:a, :b, :c]] 

1) ich diesen

a.each{|(x, y), z| p z} # => :b 

verstehen, dass es zwei Variablen (x, y) und z, so dass das dritte Element :c wird weggeworfen, und z Streichhölzer :b. Und ich verstehe dieses

a.each{|(x, y), z| p y} # => nil 

dass (x, y) Streichhölzer :a, und da es kein Array ist, gibt es keine Elemente, und so y Streichhölzer nil.

Aber wie funktioniert

a.each{|(x, y), z| p x} # => :a 

Arbeit? Ich erwarte, dass nil zurückgegeben wird.

2) Warum sind die Rückgabewerte so?

a.each{|(x, y)| p x} #=> :a 
a.each{|(x, y)| p y} #=> :b 

Ich erwarte, dass sie beide zurückgeben.

Antwort

9

Es ist wegen der Syntax von parallele Zuordnung.

a = [[:a, :b, :c]] 

So hat a.each nur ein Element iterieren, das ist [: a, b, c].

Im ersten Fall:

(x, y), z = [:a, :b, :c] 
#=> x == :a, y == nil, z == :b 

hier (x, y) ein Array erstes Element übereinstimmen: a, x und wird es dann z einfach das zweite Element übereinstimmen: b.

Und im zweiten Fall:

(x, y) = [:a, :b, :c] 
#=> x == :a, y == :b 

hier (x, y) als ein ganzes Array das Array entsprechen [: a, b, c], also x, y erhalten: a und b entsprechend.

Dies ist genau wie require args + optionale args (Schlüsselwort args) + Rest args combination match lieferte Argumente. Sei einfach "schlau", um Argumente nacheinander zu nehmen.

Noch ein kluges Beispiel:

(a,b) = 1,2 
=> [1, 2] # array match 
#=> a == 1, b == 2 

(a,b)=[1,2] 
=> [1, 2] # array match 
#=> a == 1, b == 2 

Für jeden Fall darüber einfach die beste Vermutung von nehmen, was zu nehmen.

+0

Okay, also im ersten Fall findet die intelligente Zuweisung zweimal statt, und im zweiten Teil davon ergibt (x, y) =: a x =: a und y = nil. Ich hab es geschafft. – sawa

+0

Schön. Ich benutze das die ganze Zeit, ohne zu merken, dass es mit der parallelen Zuweisung verbunden war. Ich habe auch einen Blog gefunden, der es "Destrukturierung" nennt. – Kelvin