Ответ 1
Вы можете выполнить это, явно передав текущую привязку:
def func(x, bdg)
eval "#{x} += 1", bdg
end
a = 5
func(:a, binding)
puts a # => 6
В Ruby можно передать по ссылке параметр с семантикой значения-типа (например, Fixnum)? Я ищу что-то похожее на ключевое слово С# ref.
Пример:
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)
Вы можете выполнить это, явно передав текущую привязку:
def func(x, bdg)
eval "#{x} += 1", bdg
end
a = 5
func(:a, binding)
puts a # => 6
Ruby не поддерживает "pass by reference" вообще. Все является объектом, и ссылки на эти объекты всегда передаются по значению. Фактически, в вашем примере вы передаете копию ссылки на объект Fixnum
по значению.
Проблема с вашим кодом заключается в том, что x += 1
не изменяет переданный объект Fixnum
, а создает новый и независимый объект.
Я думаю, Java-программисты вызывают Fixnum
объекты неизменяемые.
В 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
Вы можете попробовать следующий трюк:
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'
http://ruby-doc.org/core-2.1.5/Fixnum.html
Объекты Fixnum имеют немедленное значение. Это означает, что когда они назначены или передается как параметры, передается фактический объект, а не ссылка на этот объект.
Также Ruby передается по значению.
Однако кажется, что составные объекты, такие как хеши, передаются по ссылке:
fp = {}
def changeit(par)
par[:abc] = 'cde'
end
changeit(fp)
p fp
дает
{:abc=>"cde"}