2008-10-02 3 views
25

В Ruby можно передать по ссылке параметр с семантикой типа значения (например, Fixnum)? Я ищу что-то похожее на C# '' ref '.'передать параметр по ссылке' в Ruby?

Пример:

def func(x) 
    x += 1 
end 

a = 5 
func(a) #this should be something like func(ref a) 
puts a #should read '6' 

Btw. Я знаю, что могу просто использовать:

a = func(a) 

ответ

30

Вы можете сделать это, явно передавая ток переплетом

def func(x, bdg) 
    eval "#{x} += 1", bdg 
end 

a = 5 
func(:a, binding) 
puts a # => 6 
18

Ruby не поддерживает «pass by reference» вообще. Все является объектом, и ссылки на эти объекты всегда передаются по значению. Фактически, в вашем примере вы передаете копию ссылки на объект Fixnum по значению.

Проблема с вашим кодом заключается в том, что x += 1 не изменяет переданный объект Fixnum, а создает совершенно новый и независимый объект.

Я думаю, Java-программисты назвали бы Fixnum объектами неизменяемым.

+3

Я не понимаю, что Ruby не передает ref, когда переменные и параметры могут содержать только ссылки на объекты. Говорить, что ссылки передаются по значению, это то же самое, что сказать, что объекты передаются по ссылке. – 2009-05-03 13:17:08

+2

@ Damien: нет, это не так. Передача по ссылке (например, в C++, C#, PHP, Perl) позволяет * присваивать * переменной, как если бы вы ее назначили во внешней области. То, что вы пытаетесь сделать здесь, было бы возможно с истинным проходом по ссылке; но не с передачей по значению ссылок. – newacct 2012-04-23 17:34:27

+6

Вы правы, я читаю ответ Кристофа и мой комментарий снова, и я не согласен с моим 2009-м. Хм ... – 2012-04-24 01:50:29

10

В Ruby вы не можете передавать параметры по ссылке. Для вашего примера вам нужно будет вернуть новое значение и назначить его переменной a или создать новый класс, содержащий значение, и передать экземпляр этого класса. Пример:

class Container 
attr_accessor :value 
def initialize value 
    @value = value 
end 
end 

def func(x) 
    x.value += 1 
end 

a = Container.new(5) 
func(a) 
puts a.value 
6

Вы можете попробовать следующий трюк:

def func(x) 
    x[0] += 1 
end 

a = [5] 
func(a) #this should be something like func(ref a) 
puts a[0] #should read '6' 
2

http://ruby-doc.org/core-2.1.5/Fixnum.html

объекты Fixnum имеют непосредственное значение. Это означает, что когда они назначены или переданы в качестве параметров, фактический объект передается, а не ссылка на на этот объект.

Также Ruby is pass by value.