Отправить метод в 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
я думаю, это должен быть ответ