Почему метод Ruby def +(other) действителен? Что на самом деле означает «другое»?

Я практикую программу Ruby для операций с 2D-координатами. Среди них меня смущает написание def +(other) и def -(other). У меня есть следующие три вопроса:

  1. Почему имя метода совпадает с именем оператора?
  2. Откуда принимаются параметры? Прошел откуда?
  3. Почему параметр other называется other, и каково его значение и процесс передачи?

это код

class Point
  attr_accessor :x, :y
  
  def initialize(x=0, y=0)
    @x, @y = x, y
  end

  def inspect # p印出(x, y)
    "(#{x}, #{y})"
  end

  def +(other)
    self.class.new(x + other.x, y + other.y)
  end

  def -(other)
    self.class.new(x - other.x, y - other.y)
  end
end

point0 = Point.new(3, 6)
point1 = Point.new(1, 8)

p point0
p point1
p point0 + point1
p point0 - point1

в конце концов он напечатает

(3, 6)
(1, 8)
(4, 14)
(2, -2)

В point0 + point1point0 — получатель, а point1 — аргумент. Большинство операторов являются реальными методами в Ruby. Полный список и несколько примеров см. в документации по методы.

Stefan 09.04.2022 09:27
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
1
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Why is the method name equal to the operator name?

Почему нет? Почему символ, используемый для определять оператора, не должен быть символом, используемым для вызов? В конце концов, именно так мы делаем это для любого другого метода: если я хочу вызвать foo, я определяю def foo.

Разработчики языка могли выбрать любое произвольное имя. Но имеет смысл, чтобы имя метода было тем же символом, который вы используете для его вызова. Вы можете себе представить путаницу, если бы разработчики языка выбрали, например, символ - для имени метода, который соответствует оператору +?

Другие языки программирования делают другой выбор. Например, в C++ имя функции, соответствующей оператору +, равно operator+. В Python имя метода, соответствующего оператору +, — __add__. (Точнее, при встрече с выражением a + b Python сначала попытается вызвать a.__add__(b), и если это не реализовано a, то он попытается «обратное добавление» b.__radd__(a).)

В C# нет имени метода, соответствующего оператору, скорее, есть ключевое слово operator, за которым следует символ, соответствующий оператору.

Если вы хотите узнать все подробности о том, как операторные выражения оцениваются в Ruby, я рекомендую ознакомиться с Разделом 11.4.3 Выражения унарных операторов и Разделом 11.4.4 Выражения бинарных операторов документа Спецификация ISO/IEC 30170:2012 Информационные технологии — Языки программирования — Ruby.

  1. Where are the parameters received? Passed from where?

Не совсем понятно, что вы хотите этим сказать. параметр — это что-то вроде «дыры» или заполнителя в определении метода. Затем эта «дыра» заполняется аргумент, когда вы фактически вызываете метод. Например, здесь:

def foo(a, b) a + b end

a и b являются параметры (точнее, обязательные позиционные параметры, они обязательное, потому что вы должны передать аргумент для них, и они позиционный, потому что какой аргумент привязывается к какому параметру в списке параметров, зависит от позиции аргумента в списке аргументов ). На самом деле вы не знаете, каким будет результат этого метода, потому что вы не знаете, что такое a и b. Это заполнители для значений, которые будут заполнены при вызове метода:

foo(2, 3)

Здесь 2 и 3 — это аргументы (точнее, позиционные аргументы). Аргумент 2 привязывается к параметру a, потому что 2 — это первый позиционный аргумент в списке аргументов, а a — первый позиционный параметр в списке параметров. Аргумент 3 привязывается к параметру b, потому что 3 — второй позиционный аргумент в списке аргументов, а b — второй позиционный параметр в списке параметров.

Итак, в конечном итоге выполняется код для этого конкретного вызова метода (замена a на 2 и b на 3):

2 + 3

Обратите внимание: это упрощенное объяснение. Ментальная модель замены каждого вхождения параметра в теле определения метода выражением аргумента является хорошим первым приближением, но на самом деле это не то, что делает Ruby. В частности, та мысленная модель, которую я только что описал, соответствует вызов по имени стратегия оценки, тогда как Ruby на самом деле использует особый случай вызов по значению стратегия оценки, называемый совместное использование вызова по объекту.

Вы можете наблюдать разницу в этом коде:

def bar(a) a + a end

bar((puts "Hello"; 23))
# Hello
#=> 46

В ментальной модели «заменить каждое вхождение параметра выражением аргумента», которая соответствует вызову по имени, код будет выглядеть следующим образом:

(puts "Hello"; 23) + (puts "Hello"; 23)
# Hello
# Hello
#=> 46

и Hello будет напечатано дважды.

Однако при вызове по значению и совместном вызове по объекту выражение аргумента оценивается перед вызовом метода, и результат этой оценки передается, поэтому фактическое выполнение кода выглядит примерно так:

__fresh_variable_with_unspeakable_name__ = (puts "Hello"; 23)
# Hello

__fresh_variable_with_unspeakable_name__ + __fresh_variable_with_unspeakable_name__
#=> 46

Если вы хотите узнать все подробности о том, как аргументы методов оцениваются в Ruby, я рекомендую ознакомиться с разделом 11.3 Выражения вызова метода, в частности с разделом 11.3.1 Общее описание и разделом 11.3.2 Аргументы метода стандарта ISO/IEC 30170:2012 Информационные технологии — Языки программирования — Ruby. Технические характеристики.

Также есть некоторая (к сожалению, неполная) информация, которую можно найти в Ruby Spec Suite, также известный как ruby/spec, в частности, в language/def_spec.rb и language/method_spec.rb.

  1. Why is the parameter other called other, and what is its value and transmission process?

Параметр other называется other, потому что именно так его назвал автор этого фрагмента кода. Они могли бы назвать это a, или b, или x, или y, или foo, или bar, или i_dont_have_the_slightest_idea_what_to_call_this_parameter_so_i_am_just_choosing_something_totally_random. Если вы хотите знать, что Зачем автор этого фрагмента кода решил назвать его other, вам нужно будет спросить автора этого фрагмента кода.

other — довольно популярное имя для «другого» операнда определения бинарного оператора не только в Ruby, как вы можете видеть, например, в документации Python. Это имеет смысл, если вы прочитаете это вслух: в объектно-ориентированном языке программирования, таком как Ruby или Python, где операторы интерпретируются как отправленные одному из операндов, один из двух операндов бинарного оператора всегда будет self или this и "другой" операнд будет... ну... "другой" операнд. Так что назвать его other вполне естественно. В Ruby это закреплено в некоторых руководствах по стилю, например, в Руководство по стилю Rubocop Ruby.

Другие вопросы по теме