44

Rubyで何sendができるかについて読んだばかりですが、このコードを見るとまだ混乱しています(クイズからですが、とにかく期限が過ぎています)

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)

最初の行が配列をxに割り当てることを理解しましたが、何が行われるのかまったくわかりません。:[] = ,0,2そこで送信が必要な理由がわかりx.[](1)ません。最後に何が行われ、x.send(:[]、2)が実行されるのかわかりません。ライン

私は本当に混乱していて、この情報をオンラインで見つけることができません。

sendが何をするかを見つけましたが、それでもこのコード全体について少し混乱していて、かなり混乱しています。

4

5 に答える 5

59

まず第一に、[](配列インデックス)のようなもの[]=はRubyの単なるメソッドです。xは、Arrayであり、配列には[]=、インデックスと設定する値の2つの引数を受け入れるメソッドがあります。

を使用sendすると、任意のパラメータを使用して、任意の「メッセージ」(メソッド呼び出し)をオブジェクトに渡すことができます。

x.send :sortたとえば、を呼び出して、「ソート」メッセージを配列に送信できます。ただし、Sortにはパラメーターは必要ないため、余分なものを渡す必要はありません。

x#[]=一方、は2つの引数を受け入れます。そのメソッドは次のように考えることができます。

def []=(index, value)
  self.set_value_at_index(index, value)
end

したがって、を呼び出すのとsend :[]=, 0, 2同じように、を使用して呼び出すことができx[0] = 2ます。きちんとね?

于 2012-10-15T08:48:32.013 に答える
24

Rubyでは、a[0] = 2実際にはの構文糖衣ですa.[]=(0, 2)

これを知っていると、それが2行目[]=で行われます。正しく推測したように、メタプログラミングを使用して2つの引数を使用してメソッドを呼び出します。

これは3行目も同じa[0]です。Rubyforのシンタックスシュガーですx.[](0)

次のコードは、あなたの例と同等の単純なものです。

x = [1, 2, 3]
x[0] = 2
x[0] + x[1] + x[2]
于 2012-10-15T08:48:04.823 に答える
22

心配しないで。このような場合、Rubyは少し注意が必要です。コードを1行ずつ調べてみましょう。

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)

最初の行

最初の行は明らかです。3つの要素の配列をxに割り当てます。そして、それだけです。

二行目

2行目は、シンボルObject#sendを渡すメソッドを呼び出しxます(で始まるものはすべて:、rubyのシンボルであることに注意してください):[]=0(a Fixnum)、および2(another Fixnum)。
ここで、sendメソッドが何をするかを確認する必要があります(すでに行ったと言ったように):

シンボルで識別されるメソッドを呼び出し、指定された引数を渡します

これは、によって識別されたメソッドを呼び出して、それに:[]=渡すこと0を意味し2ます。Array#[]=それでは、メソッドを見てみましょう。このメソッド定義(必要に応じてオーバーロードすることができます)は次のとおりです。

class Array
    # ...
    def []=(a, b)
        # ...
    end
end

このメソッドは、私に言わせればかなり醜いものsendとして呼び出されます。x.[]=(0, 2)これが、Rubyがシンタックスシュガーバージョンを定義している理由x[0] = 2です。

x.[]=(a, b)  -->  x[a] = b

このArray場合、次のものもあります。

x.[](a)  -->  x[a]

どちらの場合も、特定のコンテキストで意味のあるバージョンを自由に呼び出すことができます。

3行目

次に、3行目と最後の行について説明します。

x[0] + x.[](1) + x.send(:[],2)

物事は本当にトリッキーになります。それを次のように分けましょう:

  1. x[0]
  2. x.[](1)
  3. x.send(:[], 2)

最初のものはかなり簡単です。配列の最初の要素を返します。

2つ目は、前に見たシンタックスシュガーで、基本的には配列の2番目の要素を返すように変換できます。x[1]

3つ目は、渡されるObject#sendメソッドを呼び出すために使用します。これは、それが呼び出すことを意味します。[]2x.[](2)x[2]

結論

コード

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)

以下を使用して変換できます:

x.send(:[]=, a, b)  -->  x.[]=(a, b)
x.send(:[], a)  -->  x.[](a)
x.[]=(a, b)  -->  x[a] = b
x.[](a)  -->  x[a]

に:

x = [1,2,3]
x[0] = 2
x[0] + x[1] + x[2]

これは次のように減らすことができます:

2 + 2 + 3

その結果:

7
于 2013-07-20T12:57:18.970 に答える
7

sendルビーでリフレクションコールを達成する方法です。したがって、この行:

x.send :[]=,0,2

と同等です:

x[0] = 2

あなたはそれをそのように読みます:メソッドの名前はsymbol(あなたの場合[]=)であり、それからあなたはパラメータ-0と2を渡します。

于 2012-10-15T08:48:32.387 に答える
2

x [0] + x [1] + x [2] = 2 + 2 + 3=7これが答えに違いないと思います

于 2013-07-20T12:18:32.050 に答える