'Passar parâmetro por referência' em Ruby?
-
03-07-2019 - |
Pergunta
Em Ruby, é possível passar por um parâmetro de referência com a semântica do tipo de valor (por exemplo, um Fixnum)? Eu estou procurando algo semelhante ao C # 's ' ref ' palavra-chave.
Exemplo:
def func(x)
x += 1
end
a = 5
func(a) #this should be something like func(ref a)
puts a #should read '6'
Btw. Eu sei que eu poderia usar apenas:
a = func(a)
Solução
Você pode fazer isso passando explicitamente na ligação atual:
def func(x, bdg)
eval "#{x} += 1", bdg
end
a = 5
func(:a, binding)
puts a # => 6
Outras dicas
Ruby não suporta "passar por referência" em tudo. Tudo é um objeto e as referências a esses objetos são sempre passados ??por valor. Na verdade, no seu exemplo você está passando uma cópia da referência ao objeto Fixnum
por valor.
O problema com o seu código é que x += 1
não modifica o objeto Fixnum
passado, mas sim cria um objeto completamente novo e independente.
Eu acho que, programadores Java chamaria objetos Fixnum
imutável .
Em Ruby você não pode passar parâmetros por referência. Para o seu exemplo, você teria que retornar o novo valor e atribuí-lo à variável um ou criar uma nova classe que contém o valor e passar uma instância dessa torno classe. Exemplo:
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
Você pode tentar a seguinte truque:
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 objetos têm valor imediato. Isto significa que quando eles são atribuídos ou passados ??como parâmetros, o objecto real é passado, em vez de uma referência a esse objeto.
No entanto, parece que os objetos compostos, como hashes, são passados ??por referência:
fp = {}
def changeit(par)
par[:abc] = 'cde'
end
changeit(fp)
p fp
dá
{:abc=>"cde"}