Переданы ли аргументы методам по ссылке или значению?

Может ли кто-нибудь расширить, исправить или проверить, что я чувствую, когда вы передаете аргументы методу в Ruby. Являются ли какие-либо из этих пунктов неправильными? Я не хватает каких-либо частей?

  • Все в Ruby - это объект.
  • Переменные - это ссылки на объекты
  • (При передаче переменной в метод): Параметр метода, который ловит переменную, является локальной переменной для этого метода. Параметр (локальная переменная) теперь также имеет ссылку на тот же объект.
  • Я мог бы изменить объект (на месте), и это изменение будет выполняться, когда объект метода будет удален. Любые переменные, ссылающиеся на этот объект вне области метода, будут отражать, что объект был изменен.
  • Новое назначение этого параметра (локальная переменная) не изменяет исходный объект, поэтому любые ссылки на него, когда метод покидает область действия, остаются неизменными.
  • Если я передаю переменную в метод, который ссылается на Integer, нет никакого способа, чтобы после выхода этого метода я мог бы иметь эту переменную, ссылающуюся на новый Integer.

Есть ли способ иметь метод, который принимает в качестве одного из своих параметров Integer, делает некоторые вещи и, возможно, как побочный эффект изменяет значение, если это изменение отражается после выхода метода. Может быть, я просто не думаю о "рубиновом пути".

Ответ 1

Все в Ruby - это объект.

Закрыть достаточно.

Переменные - это ссылки на объекты

Нет. Переменная "называет" объект: когда переменная оценивается, она вычисляет объект, который он в настоящее время "называет". Внутренне это делается путем "хранения указателя" (или эквивалентного механизма) для объекта. (Хотя для реализации не обязательно использовать указатели: в Ruby MRI, например, значения Fixnum фактически существуют без реального объекта.)

(При передаче переменной в метод): Параметр метода, который ловит переменную, является локальной переменной для этого метода. Параметр (локальная переменная) теперь также имеет ссылку на тот же объект.

Нет. См. Выше. Однако обе переменные теперь называют (или "оценивают" ) один и тот же объект. Параметры передаются внутренне с помощью Call-by-Value - то есть внутри, указатели на объекты передаются - хотя Ruby имеет "Передача вызовов по объектам" , что является термином, который я пытаюсь продвигать, поскольку я нахожу его кратким описанием поведения.

Я мог бы изменить объект (на месте), и это изменение будет выполняться, когда объект метода выходит из него. Любые переменные, ссылающиеся на этот объект вне области метода, будут отражать, что объект был изменен.

Да, сам объект. Если вы мутируете этот объект, вы мутируете этот объект повсюду. Но обратите внимание: ни одна из переменных не изменяется. И внутренние, и внешние переменные будут по-прежнему указывать (или "оценивать" ) один и тот же объект.

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

Правильно. Если вы назначаете другое значение локальной переменной, которую вы делаете, то локальная переменная называет другой объект. Ruby не является Call-by-Reference, поэтому переменная в вызывающем контексте не изменяется.

Если я передаю переменную в метод, который ссылается на Integer, нет никакого способа, чтобы после выхода этого метода я мог бы иметь эту переменную, ссылающуюся на новый Integer?

Переменные никогда не передаются. Переменные оцениваются для объектов, которые они называют, и эти объекты передаются. В любом случае, мы знаем, что:

  • Ruby не является Call-by-Reference и
  • Целые числа (Fixnums) неизменяемы

Таким образом:

x = 1
y.foo(x)

никогда не может изменять имена x, а также не может изменять содержимое имен объектов x (потому что это, ну, неизменяемо). Даже если объект, который был назван x, был изменен, метод не мог изменить имена объектов x: он мог только мутировать объект, полученный в результате оценки x.

Счастливое кодирование.


Теперь Ruby Way - в моей книге - будет использовать лучшее возвращаемое значение, которое объединило бы все новое состояние, и позвольте вызывающему абоненту положить его туда, куда ему нужно: -)

Конечно, изменяемые объекты (включая простые массивы) также являются опцией, но это ик. И, если есть достаточно состояния, которое перемещается вместе, это может быть кандидат для отдельного класса.


В качестве заключительной заметки: Ruby поддерживает концепцию замыканий, поэтому это возможно в лексическом режиме:

x = 1; (lamb­da {|a| x = a}).c­all(2); x  // => 2

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