Метод Ruby, Proc и путаница блоков
У меня есть пара вопросов о методах, процедурах и блоках Ruby, которые кажутся мне довольно странными. Это не столько синтаксис или функция, сколько логика решений.
Вопрос 1:
Почему блоки могут быть переданы методам (например, каждый), но они не могут быть назначены переменной?
Я знаю, что вы можете передавать их в процедурах, т.е. p = Proc.new {...}
(доступ с помощью &p
), но не имеет большого смысла заставить программиста использовать эти средства.
Вопрос 2:
Почему существует дифференциация между методами и процедурами?
Например, я могу выполнить задачу определения функции и вызова этой функции двумя способами:
def square(x)
x**2
end
square(3)
=> 9
или
square = lambda {|x| x**2}
square.call(3)
=> 9
Почему дифференциация? В Python, например, как определение функции стандартным способом, так и square = lambda x: x**2
выполняет ту же задачу создания функции и назначения ее square
.
Ответы
Ответ 1
Вопрос 1: Блоки не являются объектами, они являются синтаксическими структурами; поэтому они не могут быть назначены переменной. Это привилегия, зарезервированная для объектов.
Вопрос 2: Методы не являются объектами, поэтому они не могут получать сообщения. И наоборот, procs и lambdas являются объектами, поэтому их нельзя вызвать подобно методам, но они должны получить сообщение, которое сообщает им, чтобы оно возвращало значение на основе параметров, переданных с сообщением.
Procs и Lambdas - это объекты, поэтому они могут получать сообщение call
и присваиваться именам. Подводя итог, это объект, который заставляет procs и lambdas вести себя так, как вы нечетны. Методы и блоки не являются объектами и не разделяют это поведение.
Ответ 2
В некоторой степени, по крайней мере, методы - это объекты:
class ABC
def some_method
end
end
ABC.instance_method(:some_method) #=> #<UnboundMethod: ABC#some_method>
Кроме того, существует встроенный класс: Method, как описано здесь.
Смотрите также это: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls
Бессмысленно <bseg>
, он скорее всего воспринимает вещь все-есть-объект. В этом конкретном случае, похоже, требуется немного больше копания, чтобы видеть.
(Я действительно должен приложить усилия, чтобы понять это лучше: я начинаю думать, что это имеет фундаментальное значение для более глубокого понимания.)
Ответ 3
Методы - это методы, то есть действия, которые объект может принимать в ответ на сообщения. Они не являются функциями.
Блоки - это блокировки - они являются функциями, которые закрываются в охватывающей области. Они не концептуально "принадлежат" к данному объекту.
В некоторых языках методы - это просто функции, которые являются членами объекта, но Ruby не рассматривает их таким образом. Разделение метода от его объекта-владельца более сродни операции, чем простому назначению. Ruby берет свою объектно-ориентированную модель от Smalltalk, дедушки современного OO.