2009-04-20 8 views
5

における並列割り当てのための配列は、あなたがRubyでこれを行うものと同様にオブジェクトの振る舞いますルビー

ar = [1, 2] 
x, y = ar 

その後、== 1とy == 2. xは、私は私の中で定義できる方法はあります同じ効果を生み出す独自のクラス?例えば

rb = AllYourCode.new 
x, y = rb 

これまでのところ、これまでの割り当てでは、x == rbとy = nilにすることができました。 Pythonには次のような機能があります。

>>> class Foo: 
...  def __iter__(self): 
...    return iter([1,2]) 
... 
>>> x, y = Foo() 
>>> x 
1 
>>> y 
2 
+0

完璧、ありがとう、これは私がこの2番目に必要なものです。 –

答えて

7

#to_aryを定義します。これにより、オブジェクトを代入の配列として扱うことができます。

irb> o = Object.new 
=> #<Object:0x3556ec> 
irb> def o.to_ary 
     [1, 2] 
    end 
=> nil 
irb> x, y = o 
=> [1,2] 
irb> x 
#=> 1 
irb> y 
#=> 2 

#to_a#to_aryの違いは#to_aryが利用可能である一方で、我々は配列として指定されたオブジェクトを扱うことができれば#to_aは、配列に 指定されたオブジェクトを変換しようとするために使用されていることです。それは微妙な違いです。

+0

確かに微妙。これは==とeqlの似たような区別ですか?私は本当に好きではありません。なぜto_aとto_aryを持つのが良いアイデアですか? – allyourcode

+1

to_aryは、効果的な配列であるオブジェクト用です。実際に配列を使用する必要があるものが配列の代わりにオブジェクトを使用でき、オブジェクトが配列でなければならない場合は、to_aryを実装する必要があります。 to_aは配列に変換可能なものです。各メソッドを持つ(終了する)オブジェクトには、to_aの明白な実装があります。例えば。ファイルはto_aメソッドを持つことができますが、配列として扱うことはできませんし、to_aryメソッドを持たないように配列をモデル化しません。 –

1

代入はメソッドではなく演算子であるため、再定義できません。しかし、AllYourCodeクラスがArrayから継承する場合、あなたの例はうまくいくでしょう。

Rubyで代入が発生すると、右辺が参照され、複数の右辺値がある場合は、それらが配列に集められます。次に、左側を見ます。そこにlvalueが1つある場合、配列に割り当てられます。

def foo 
    return "a", "b", "c" # three rvalues 
end 

x = foo # => x == ["a", "b", "c"] 

つ以上の左辺値が(より具体的には、カンマを見れば)があれば、それは連続的に右辺値を割り当て、余分なものを捨てます。

x, y, z = foo # => x == "a", y == "b", z == "c" 
x, y = foo # => x == "a", y == "b" 
x, = foo  # => x == "a" 

アレイが返された場合でも、並列割当てを行うことができます。

def bar 
    ["a", "b", "c"] 
end 

x = bar  # => x == ["a", "b", "c"] 
x, y, z = bar # => x == "a", y == "b", z == "c" 
x, y = bar # => x == "a", y == "b" 
x, = bar  # => x == "a" 

したがって、rbが配列であるか、配列から継承する場合、xとyには最初の2つの値が割り当てられます。

+0

私はあなたの最初の例で "a"、 "b"、 "c"の前後に括弧を入れることを意味すると思います。私はそれを試したとき、私は構文エラーがあります。 – allyourcode

+0

実際に私は "返品"を忘れました。今修正されました。 –

2

ほとんど:

class AllYourCode 
    def to_a 
    [1,2] 
    end 
end 

rb = AllYourCode.new 
x, y = *rb 
p x 
p y 

スプラットはto_aryを起動しようとし、その後、to_aを起動しようとします。なぜこれをやりたいのか分かりませんが、これは実際にArrayの機能ではなく、その実装でArrayを使用する構文的な機能です。

言い換えれば、複数の割り当てのためのユースケースは、のようなものである:すなわち

# swap 
x, y = y, x 

# multiple return values 
quot, rem = a.divmod(b) 

# etc. 
name, age = "Person", 100 

は、オブジェクトが(Array)から割り当てられた時間のほとんども明らかではありません。

+2

これはやや助けになりますが、私は質問をすると嫌いですし、人々は私がやろうとしていることをする良い理由がないと信じています。これが悪い考えだと思うなら、理由を説明してください!!私はあなたの例に感謝しますが、典型的な使用方法を示しても、何をしようとしているのが間違っているのか説明できません:/ – allyourcode

+0

私はあなたに正当な理由がないとは言いませんでした。理由は私はそれが何であるかを知るまで、それが良いかどうかについての意見を声に出すことはできません。私は確かにあなたがこれをしたいと思う状況がないとは言えませんが、あなたが私の好奇心に惑わされるなら、私はそれを感謝します。 –