Отправить метод в Ruby

Я только что прочитал о том, что send делает в Ruby, и я все еще запутался, глядя на этот код (это из викторины, но в прошлый срок).

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

Я понимаю, что первая строка присваивает массив x то я не понимаю, что делает :[] = ,0,2 вообще, и я не понимаю, почему нужно отправлять туда Я не понимаю, что делает x.[](1), а x.send(: [], 2) делает в последней строке

Я действительно смущен, и я просто не могу найти эту информацию в Интернете.

Я нашел, что отправляет, но я все еще немного запутался и немного запутался в этом коде в целом.

Ответ 1

Прежде всего, такие вещи, как [] (индекс массива) и []=, являются просто методами в Ruby. x - это Array, а массивы имеют метод []=, который принимает два аргумента, индекс и значение для установки.

Используя send, вы можете передать произвольное "сообщение" (вызов метода) объекту с произвольными параметрами.

Вы можете вызвать x.send :sort, например, чтобы отправить сообщение "sort" в массив. Сортировка не нуждается ни в каких параметрах, поэтому нам не нужно передавать что-либо дополнительное.

x#[]=, с другой стороны, принимает два аргумента. Его метод можно представить так:

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

Итак, мы можем просто вызвать его с помощью send :[]=, 0, 2, который похож на вызов x[0] = 2. Аккуратно, да?

Ответ 2

В Ruby a[0] = 2 на самом деле синтаксический сахар для a.[]=(0, 2).

Зная это, это то, что делает вторая строка - он вызывает метод []= с двумя аргументами, используя метапрограммирование, как вы правильно догадались.

Это то же самое для вашей третьей строки: a[0] - синтаксический сахар в Ruby для x.[](0).

Следующий код является более простым эквивалентом вашему примеру:

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

Ответ 3

Не волнуйся. В этих случаях Ruby может быть немного сложнее. Давайте рассмотрим код по строкам:

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

Первая строка

Первая строка вам понятна: она назначает массив из трех элементов x. И это как раз.

Вторая строка

Вторая строка вызывает Object#send метод x, передающий символ (помните, что все, что начинается с :, является символом в рубине) :[]=, 0 (a Fixnum) и 2 (другое Fixnum).
Теперь вам просто нужно взглянуть на то, что делает метод отправки (как вы сказали, вы уже сделали):

Вызывает метод, идентифицированный символом, передавая ему любые указанные аргументы

Это означает, что он вызовет метод, идентифицированный :[]=, и передаст ему 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]

В обоих случаях вы можете вызывать любую версию, имеющую смысл для вас в конкретном контексте.

Третья строка

Теперь для третьей и последней строки:

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

все становится очень сложно. Пусть делятся на:

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

Первый из них довольно прямолинейный. Он возвращает первый элемент массива.

Второй - это синтаксический сахар, который мы видели ранее, который может быть в основном преобразован в x[1], который возвращает второй элемент массива.

Третий использует Object#send для вызова метода [], передающего ему 2. Это означает, что он вызывает x.[](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

Ответ 4

send - это способ достижения рефлексивных вызовов в рубине. Таким образом, эта строка:

x.send :[]=,0,2

Является эквивалентным:

x[0] = 2

вы читаете его таким образом: имя метода является символом (в вашем случае []=), а затем вы передаете параметры - 0 и 2.

Ответ 5

х [0] + х [1] + х [2] = 2 + 2 + 3 = 7 я думаю, это должен быть ответ