"passer paramètre par référence" en Ruby?
-
03-07-2019 - |
Question
En Ruby, est-il possible de passer par référence un paramètre avec une sémantique de type valeur (par exemple, un Fixnum)? Je recherche quelque chose de similaire au mot clé ' ref ' de C #.
Exemple:
def func(x)
x += 1
end
a = 5
func(a) #this should be something like func(ref a)
puts a #should read '6'
Btw. Je sais que je pourrais simplement utiliser:
a = func(a)
La solution
Vous pouvez y parvenir en transmettant explicitement la liaison actuelle:
def func(x, bdg)
eval "#{x} += 1", bdg
end
a = 5
func(:a, binding)
puts a # => 6
Autres conseils
Ruby ne prend pas en charge "passage par référence". du tout. Tout est un objet et les références à ces objets sont toujours passées par valeur. En fait, dans votre exemple, vous transmettez une copie de la référence à Fixnum
Objet par valeur.
Le problème avec votre code est que x + = 1
ne modifie pas l'objet Fixnum
transmis, mais crée plutôt un objet entièrement nouveau et indépendant.
Je pense que les programmeurs Java appellent les objets Fixnum
immuables .
En Ruby, vous ne pouvez pas transmettre de paramètres par référence. Pour votre exemple, vous devez renvoyer la nouvelle valeur et l'affecter à la variable a ou créer une nouvelle classe contenant la valeur et transmettre une instance de cette classe. Exemple:
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
Vous pouvez essayer le truc suivant:
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
Les objets Fixnum ont une valeur immédiate. Cela signifie que quand ils sont assignés ou passé en tant que paramètres, l'objet réel est passé, plutôt qu'une référence à cet objet.
Cependant, il semble que les objets composites, comme les hachages, soient passés par référence:
fp = {}
def changeit(par)
par[:abc] = 'cde'
end
changeit(fp)
p fp
donne
{:abc=>"cde"}