Ruby передается по ссылке или по значению?

248
@user.update_languages(params[:language][:language1], 
                       params[:language][:language2], 
                       params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------" 
                + lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@userОбъект добавляет ошибки к lang_errorsпеременной в update_lanugagesметоде. когда я выполняю сохранение @userобъекта, я теряю ошибки, которые изначально были сохранены в lang_errorsпеременной.

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

Sid
источник
Я также замечаю, что могу сохранить это значение в клонированном объекте
Сид
1
Вы должны посмотреть на ответ Эйба Фолькера. Но после бега вокруг блока вот как я бы это сказал. когда вы передаете объект Foo в процедуру, копия ссылки на объект передается, bar, Pass by value. Вы не можете изменить объект, на который указывает Foo, но вы можете изменить содержимое объекта, на который он указывает. Поэтому, если вы передадите массив, содержимое массива можно изменить, но вы не сможете изменить, на какой массив ссылаются. Приятно иметь возможность использовать методы Foo, не беспокоясь о том, чтобы испортить другие зависимости от Foo.
bobbdelsol

Ответы:

244

В традиционной терминологии Ruby строго передается по значению . Но это не совсем то, что вы спрашиваете здесь.

Ruby не имеет понятия чистого, не ссылочного значения, поэтому вы определенно не можете передать его методу. Переменные всегда являются ссылками на объекты. Чтобы получить объект, который не изменится из-под вас, вам нужно дублировать или клонировать переданный вами объект, таким образом давая объект, на который никто больше не ссылается. (Однако даже это не является пуленепробиваемым - оба стандартных метода клонирования делают поверхностное копирование, поэтому переменные экземпляра клона по-прежнему указывают на те же объекты, что и оригиналы. Если объекты, на которые ссылается ивар, видоизменяются, это будет по-прежнему отображаются в копии, поскольку ссылаются на те же объекты.)

цыпленок
источник
88
Ruby передается по значению . Нет, если Никаких "но. Без исключений. Если вы хотите знать , является ли Ruby (или любой другой язык) является пройти по ссылке или передать по значению , просто попробуйте это: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}".
Йорг Миттаг
95
@ JörgWMittag: Да, но путаница ОП на самом деле не является передачей по значению или передачей по ссылке в строгом смысле слова CS. Чего ему не хватало, так это того, что передаваемые вами «ценности» являются ссылками. Я чувствовал, что просто сказать «это по значению» было бы педантично и нанести ФП плохую услугу, поскольку на самом деле это не то, что он имел в виду. Но спасибо за разъяснения, потому что это важно для будущих читателей, и я должен был включить это. (Я всегда разрываюсь между включением дополнительной информации и не путаю людей.)
Чак
16
Не согласен с @Jorg. Руби передается по ссылке, он просто меняет ссылку. Попробуйте вместо этого: def foo (bar) bar.replace 'reference' end; baz = 'значение'; Foo (БАЗ); ставит "Ruby
мимоходом
15
@pguardiario: я думаю, что это действительно вопрос определений. Вы используете определение «передача по ссылке», которое вы лично придумали, в то время как Йорг использует традиционное определение информатики. Конечно, это не мое дело, чтобы рассказать вам, как использовать слова - я просто думаю, что важно объяснить, что термин обычно означает. В традиционной терминологии Ruby передается по значению, но сами значения являются ссылками. Я полностью понимаю, почему вам и ФП нравится думать об этом как о передаче по ссылке - это просто не традиционный смысл этого термина.
Чак
7
Все в Ruby является объектом, поэтому Ruby не передается ни по значению, ни по ссылке, по крайней мере в том смысле, в каком эти термины используются в C ++. «передача по ссылке на объект» может быть лучшим способом описать, что делает Ruby. В конце концов, лучше всего было бы не придавать слишком много значения ни одному из этих терминов, а просто получить хорошее представление о том, что действительно происходит.
Дэвид Винецки
424

Остальные ответчики все правы, но друг попросил меня объяснить ему это, и что на самом деле сводится к тому, как Ruby обрабатывает переменные, поэтому я подумал, что поделюсь некоторыми простыми картинками / объяснениями, которые я написал для него (извинения за длину и, вероятно, некоторое упрощение)


В1: Что происходит, когда вы назначаете новую переменную strзначению 'foo'?

str = 'foo'
str.object_id # => 2000

введите описание изображения здесь

A: Создана вызываемая метка, strкоторая указывает на объект 'foo', который для состояния этого интерпретатора Ruby оказывается в ячейке памяти 2000.


Q2: Что происходит, когда вы назначаете существующую переменную strновому объекту с помощью =?

str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002

введите описание изображения здесь

A: Метка strтеперь указывает на другой объект.


Q3: что происходит, когда вы назначаете новую переменную = в str?

str2 = str
str2.object_id # => 2002

введите описание изображения здесь

A: Создана новая метка с именем, str2которая указывает на тот же объект, что и str.


Q4: что произойдет, если объект, на который ссылается str и str2будет изменен?

str2.replace 'baz'
str2 # => 'baz'
str  # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002

введите описание изображения здесь

A: Обе метки по-прежнему указывают на один и тот же объект, но сам объект мутировал (его содержимое изменилось на что-то другое).


Как это связано с первоначальным вопросом?

В основном это то же самое, что происходит в Q3 / Q4; метод получает свою собственную частную копию переменной / label ( str2), которая передается ему ( str). Он не может изменить объект, на который str указывает метка , но он может изменить содержимое объекта, на который они оба ссылаются, чтобы содержать else:

str = 'foo'

def mutate(str2)
  puts "str2: #{str2.object_id}"
  str2.replace 'bar'
  str2 = 'baz'
  puts "str2: #{str2.object_id}"
end

str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004
Абе Воелкер
источник
1
Роберт Хитон также недавно писал об этом в блоге: robertheaton.com/2014/07/22/…
Майкл Реннер,
48

Ruby использует «передачу по ссылке на объект»

(Используя терминологию Python.)

Сказать, что в Ruby используется «передача по значению» или «передача по ссылке», на самом деле недостаточно, чтобы быть полезным. Я думаю, что, как большинство людей знают это в наши дни, эта терминология («значение» против «ссылка») происходит из C ++.

В C ++ «передача по значению» означает, что функция получает копию переменной, и любые изменения в копии не изменяют оригинал. Это верно и для объектов. Если вы передаете переменную объекта по значению, тогда весь объект (включая все его члены) копируется, и любые изменения в элементах не изменяют эти элементы в исходном объекте. (Другое дело, если вы передаете указатель по значению, но в Ruby все равно нет указателей, AFAIK.)

class A {
  public:
    int x;
};

void inc(A arg) {
  arg.x++;
  printf("in inc: %d\n", arg.x); // => 6
}

void inc(A* arg) {
  arg->x++;
  printf("in inc: %d\n", arg->x); // => 1
}

int main() {
  A a;
  a.x = 5;
  inc(a);
  printf("in main: %d\n", a.x); // => 5

  A* b = new A;
  b->x = 0;
  inc(b);
  printf("in main: %d\n", b->x); // => 1

  return 0;
}

Вывод:

in inc: 6
in main: 5
in inc: 1
in main: 1

В C ++ «передача по ссылке» означает, что функция получает доступ к исходной переменной. Он может назначить целое новое литеральное целое число, и тогда исходная переменная также будет иметь это значение.

void replace(A &arg) {
  A newA;
  newA.x = 10;
  arg = newA;
  printf("in replace: %d\n", arg.x);
}

int main() {
  A a;
  a.x = 5;
  replace(a);
  printf("in main: %d\n", a.x);

  return 0;
}

Вывод:

in replace: 10
in main: 10

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

В Ruby используется «передача по ссылке на объект» (для использования терминологии Python):

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

Поэтому Ruby не использует «передачу по ссылке» в смысле C ++. Если это так, то присвоение нового объекта переменной внутри функции приведет к тому, что старый объект будет забыт после возврата функции.

class A
  attr_accessor :x
end

def inc(arg)
  arg.x += 1
  puts arg.x
end

def replace(arg)
  arg = A.new
  arg.x = 3
  puts arg.x
end

a = A.new
a.x = 1
puts a.x  # 1

inc a     # 2
puts a.x  # 2

replace a # 3
puts a.x  # 2

puts ''

def inc_var(arg)
  arg += 1
  puts arg
end

b = 1     # Even integers are objects in Ruby
puts b    # 1
inc_var b # 2
puts b    # 1

Вывод:

1
2
2
3
2

1
2
1

Вот почему в Ruby, если вы хотите изменить объект внутри функции, но забыть об этих изменениях при возврате функции, вы должны явно сделать копию объекта, прежде чем вносить временные изменения в копию.

Дэвид Винецки
источник
Твой ответ самый лучший. Я также хочу опубликовать простой пример def ch(str) str.reverse! end; str="abc"; ch(str); puts str #=> "cba"
fangxing
Это правильный ответ! Это также очень хорошо объяснено здесь: robertheaton.com/2014/07/22/… . Но то , что я до сих пор не понимаю , это: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}". Это печатает "Рубин передается по значению". Но переменная внутри fooпереназначена. Если barбы был массив, переназначение не произойдет baz. Зачем?
Хаффла
Я не понимаю твой вопрос. Я думаю, что вы должны задать совершенно новый вопрос, а не в комментариях здесь.
Дэвид Винецки
42

Ruby передается по ссылке или по значению?

Ruby передается по значению. Всегда. Без исключений. Нет, если Никаких "но.

Вот простая программа, которая демонстрирует этот факт:

def foo(bar)
  bar = 'reference'
end

baz = 'value'

foo(baz)

puts "Ruby is pass-by-#{baz}"
# Ruby is pass-by-value
Йорг Миттаг
источник
15
@DavidJ .: «Ошибка здесь в том , что локальный параметр переназначен (указывает на новое место в памяти)» - Это не ошибка, это определение из передачи по значению . Если бы Ruby передавался по ссылке, то переназначение привязки аргумента локального метода в вызываемом объекте также переназначило бы привязку локальной переменной в вызывающей стороне. Что это не так. Ergo, Ruby передается по значению. Тот факт, что если вы изменяете изменяемое значение, то это значение совершенно не имеет значения, именно так работает изменяемое состояние. Ruby не является чисто функциональным языком.
Йорг Миттаг
5
Благодаря Jörg, чтобы защитить истинное определение «передача по значению». Ясно, что наш мозг тает, когда значение на самом деле является ссылкой, хотя рубин всегда проходит мимо значения.
Дуглас
9
Это софистика. Практическое различие между «передачей по значению» и «передачей по ссылке» является семантическим, а не синтаксическим. Вы сказали бы, что массивы C передаются по значению? Конечно, нет, даже если вы передаете имя массива функции, вы передаете неизменный указатель, и только данные, на которые ссылается указатель, могут быть изменены. Ясно, что типы значений в Ruby передаются по значению, а ссылочные типы передаются по ссылке.
dodgethesteamroller
3
@dodgethesteamroller: Ruby и C передаются по значению. Всегда. Нет исключений, если нет, но нет. Различие между передачей по значению и передачей по ссылке заключается в том, передаете ли вы значение, на которое указывает ссылка, или передаете ссылку. C всегда передает значение, а не ссылку. Значение может или не может быть указателем, но то , что это значение не имеет никакого отношения к ли она передается в первую очередь. Ruby также всегда передает значение, а не ссылку. Это значение всегда является указателем, но опять же, это не имеет значения.
Йорг Миттаг
44
Этот ответ, хотя и строго говоря, правда , не очень полезен . Тот факт, что передаваемое значение всегда является указателем, не имеет значения. Это источник путаницы для людей, которые пытаются учиться, и ваш ответ абсолютно не поможет справиться с этой путаницей.
20

Ruby в строгом смысле передается по значению, НО значения являются ссылками.

Это можно назвать « передачей по значению ». Эта статья имеет лучшее объяснение, которое я читал: http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/

Передача-ссылка-значение может быть кратко объяснена следующим образом:

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

Получающееся поведение фактически является комбинацией классических определений передачи по ссылке и передачи по значению.

Ari
источник
«передать ссылку по значению» - это та же фраза, которую я использую для описания передачи аргументов Руби. Я думаю, что это самая точная и лаконичная фраза.
Уэйн Конрад
16

Уже есть несколько хороших ответов, но я хочу опубликовать определение пары авторитетов по этому вопросу, но также надеюсь, что кто-то может объяснить, что сказали авторитеты Матц (создатель Ruby) и Дэвид Фланаган в своей превосходной книге О'Рейли, Язык программирования Ruby .

[из 3.8.1: Ссылки на объекты]

Когда вы передаете объект методу в Ruby, это ссылка на объект, которая передается методу. Это не сам объект, и это не ссылка на ссылку на объект. Другой способ сказать, что аргументы метода передаются по значению, а не по ссылке , но что переданные значения являются ссылками на объекты.

Поскольку ссылки на объекты передаются методам, методы могут использовать эти ссылки для изменения базового объекта. Эти модификации затем видны, когда метод возвращается.

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

Доминик
источник
1
Потому что ссылка не изменяется; базовый объект
dodgethesteamroller
1
Потому что объект изменчив. Руби не является чисто функциональным языком. Это полностью ортогонально передаче по ссылке или передаче по значению (за исключением того факта, что в чисто функциональном языке передача по значению и передача по ссылке всегда дают одинаковые результаты, поэтому язык может используйте один или оба без вашего ведома).
Йорг Миттаг,
Хорошим примером будет, если вместо назначения переменной в функции вы посмотрите на случай передачи хеша функции и выполнения слияния! на переданный хеш. Оригинальный хэш в итоге модифицируется.
Elc
16

Ruby передается по ссылке или по значению?

Руби это передача по ссылке. Всегда. Без исключений. Нет, если Никаких "но.

Вот простая программа, которая демонстрирует этот факт:

def foo(bar)
  bar.object_id
end

baz = 'value'

puts "#{baz.object_id} Ruby is pass-by-reference #{foo(baz)} because object_id's (memory addresses) are always the same ;)"

=> 2279146940 Ruby является передачей по ссылке 2279146940, потому что object_id (адреса памяти) всегда одинаковы;)

def bar(babar)
  babar.replace("reference")
end

bar(baz)

puts "some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-#{baz}"

=> некоторые люди не понимают, что это ссылка, потому что локальное назначение может иметь приоритет, но оно явно передается по ссылке

Бретт Оллред
источник
Это единственный правильный ответ и он дает несколько хороших ошибок: Try a = 'foobar'; б = а; b [5] = 'z', a и b изменятся.
Мартейн
2
@ Martijn: ваш аргумент не совсем верен. Давайте пройдемся по вашей заявке кода за заявлением. a = 'foobar' создает новую ссылку, указывающую на 'foobar'. b = a создает вторую ссылку на те же данные, что и a. b [5] = 'z' изменяет шестой символ значения, на которое ссылается b, на 'z' (значение, на которое по совпадению также ссылается a, изменяется). Вот почему «оба модифицируются» в ваших терминах, или, точнее, почему «значение, на которое ссылаются обе переменные, модифицируется».
Lukas_Skywalker
2
Вы ничего не делаете со ссылкой в ​​вашем barметоде. Вы просто модифицируете объект, на который указывает ссылка , но не саму ссылку. Единственный способ изменить ссылки в Ruby - по назначению. Вы не можете изменять ссылки, вызывая методы в Ruby, потому что методы можно вызывать только для объектов, а ссылки не являются объектами в Ruby. Ваш пример кода демонстрирует, что Ruby имеет общее изменяемое состояние (что здесь не обсуждается), однако он ничего не делает для того, чтобы осветить различие между передачей по значению и передачей по ссылке.
Йорг Миттаг
1
Когда кто-то спрашивает, является ли язык «передачей по ссылке», он обычно хочет знать, когда вы передаете что-то в функцию, и функция изменяет это, будет ли оно изменено вне функции. Для Руби ответ «да». Этот ответ полезен для демонстрации того, что ответ @ JörgWMittag крайне бесполезен.
Тоби 1 Кеноби
@ Toby1Kenobi: Вы, конечно, можете использовать собственное определение термина «передача по стоимости», которое отличается от распространенного, широко используемого определения. Однако, если вы сделаете это, вы должны быть готовы к тому, что люди будут сбиты с толку, особенно если вы пренебрегаете тем, что говорите о совершенно другом, в некоторых аспектах даже противоположном понятии, чем все остальные. В частности, «передача по ссылке» не связана с тем, может ли передаваемое «что-то» быть измененным, а скорее с тем , чем является это «что-то», в частности, является ли это ссылкой…
Йорг В. Mittag
8

Параметры являются копией оригинальной ссылки. Таким образом, вы можете изменить значения, но не можете изменить исходную ссылку.

Раэль Гугельмин Кунья
источник
2

Попробуй это:--

1.object_id
#=> 3

2.object_id
#=> 5

a = 1
#=> 1
a.object_id
#=> 3

b = 2
#=> 2
b.object_id
#=> 5

идентификатор a содержит object_id 3 для объекта значения 1, а идентификатор b содержит object_id 5 для объекта значения 2.

Теперь сделайте это:

a.object_id = 5
#=> error

a = b
#value(object_id) at b copies itself as value(object_id) at a. value object 2 has object_id 5
#=> 2

a.object_id 
#=> 5

Теперь, a и b оба содержат один и тот же object_id 5, который ссылается на объект значения 2. Таким образом, переменная Ruby содержит object_ids для ссылки на объекты значения.

Выполнение следующих действий также дает ошибку:

c
#=> error

но это не даст ошибки:

5.object_id
#=> 11

c = 5
#=> value object 5 provides return type for variable c and saves 5.object_id i.e. 11 at c
#=> 5
c.object_id
#=> 11 

a = c.object_id
#=> object_id of c as a value object changes value at a
#=> 11
11.object_id
#=> 23
a.object_id == 11.object_id
#=> true

a
#=> Value at a
#=> 11

Здесь идентификатор возвращает значение объекта 11, чей идентификатор объекта равен 23, то есть object_id 23 находится на идентификаторе a. Теперь мы видим пример с использованием метода.

def foo(arg)
  p arg
  p arg.object_id
end
#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23

Аргумент в foo присваивается с возвращаемым значением х. Это ясно показывает, что аргумент передается значением 11, а значение 11 само по себе является объектом с уникальным идентификатором объекта 23.

Теперь посмотрите также:

def foo(arg)
  p arg
  p arg.object_id
  arg = 12
  p arg
  p arg.object_id
end

#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23
#=> 12
#=> 25
x
#=> 11
x.object_id
#=> 23

Здесь идентификатор arg сначала содержит object_id 23 для ссылки 11, а после внутреннего присваивания со значением объекта 12 он содержит object_id 25. Но он не меняет значение, на которое ссылается идентификатор x, используемый в вызывающем методе.

Следовательно, Ruby передается по значению, а переменные Ruby не содержат значений, но содержат ссылку на объект значения.

Алок Ананд
источник
1

Руби интерпретируется. Переменные - это ссылки на данные, но не сами данные. Это облегчает использование одной и той же переменной для данных разных типов.

Присвоение lhs = rhs затем копирует ссылку на rhs, а не данные. Это отличается в других языках, таких как C, где присваивание копирует данные в lhs из rhs.

Таким образом, для вызова функции переданная переменная, скажем, x, действительно копируется в локальную переменную в функции, но x является ссылкой. Затем будет две копии ссылки, обе ссылаются на одни и те же данные. Один будет в звонящем, другой в функции.

Назначение в функции затем скопирует новую ссылку на версию функции x. После этого версия вызывающего абонента x остается неизменной. Это все еще ссылка на исходные данные.

Напротив, использование метода .replace для x приведет к тому, что ruby ​​сделает копию данных. Если замена используется перед любыми новыми назначениями, тогда вызывающая сторона также увидит изменение данных в своей версии.

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

'Вызов по значению' или 'Вызов по ссылке' здесь запутан из-за путаницы над '=' В скомпилированных языках '=' является копией данных. Здесь на этом интерпретируемом языке '=' является справочной копией. В этом примере передается ссылка, за которой следует ссылочная копия, хотя '=', которая перекрывает оригинал, переданный в ссылке, а затем люди говорят об этом, как если бы '=' была копией данных.

Чтобы соответствовать определениям, мы должны придерживаться «.replace», так как это копия данных. С точки зрения «.replace» мы видим, что это действительно передача по ссылке. Кроме того, если мы пройдем через отладчик, мы увидим, что ссылки передаются, поскольку переменные являются ссылками.

Однако если мы должны сохранить '=' в качестве системы отсчета, тогда мы действительно увидим переданные данные вплоть до назначения, а затем мы больше не увидим их после назначения, пока данные вызывающей стороны остаются неизменными. На поведенческом уровне это передается по значению, пока мы не считаем переданное значение составным - поскольку мы не сможем сохранить его часть при изменении другой части в одном назначении (как это назначение изменяет ссылку и оригинал выходит за рамки видимости). Также будет бородавка, в этом случае переменные в объектах будут ссылками, как и все переменные. Следовательно, мы будем вынуждены говорить о передаче «ссылки по значению» и должны использовать связанные выражения.


источник
1

Следует отметить, что вам даже не нужно использовать метод «заменить», чтобы изменить исходное значение. Если вы назначите одно из значений хеш-функции для хэша, вы измените исходное значение.

def my_foo(a_hash)
  a_hash["test"]="reference"
end;

hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"
Дон карр
источник
Еще одна вещь, которую я нашел. Если вы передаете числовой тип, все числовые типы являются неизменяемыми и, следовательно, передаются по значению. Функция замены, которая работала со строкой выше, НЕ работает ни для одного из числовых типов.
Дон Карр
1
Two references refer to same object as long as there is no reassignment. 

Любые обновления в том же объекте не будут ссылаться на новую память, поскольку она все еще находится в той же памяти. Вот несколько примеров:

    a = "first string"
    b = a



    b.upcase! 
    => FIRST STRING
    a
    => FIRST STRING

    b = "second string"


a
    => FIRST STRING
    hash = {first_sub_hash: {first_key: "first_value"}}
first_sub_hash = hash[:first_sub_hash]
first_sub_hash[:second_key] = "second_value"

    hash
    => {first_sub_hash: {first_key: "first_value", second_key: "second_value"}}

    def change(first_sub_hash)
    first_sub_hash[:third_key] = "third_value"
    end

    change(first_sub_hash)

    hash
    =>  {first_sub_hash: {first_key: "first_value", second_key: "second_value", third_key: "third_value"}}
Айман Хуссейн
источник
0

Да, но ....

Ruby передает ссылку на объект, и поскольку все в ruby ​​является объектом, вы можете сказать, что он передается по ссылке.

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

Однако, по сути, он «скрывает» поведение, потому что большинство операций ruby ​​предоставляет «из коробки» - например, строковые операции создают копию объекта:

> astringobject = "lowercase"

> bstringobject = astringobject.upcase
> # bstringobject is a new object created by String.upcase

> puts astringobject
lowercase

> puts bstringobject
LOWERCASE

Это означает, что большую часть времени исходный объект остается неизменным, создавая впечатление, что ruby ​​является «передачей по значению».

Конечно, при разработке ваших собственных классов понимание деталей этого поведения важно как для функционального поведения, эффективности памяти и производительности.

Томм П
источник