2008-10-02 5 views
25

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 cherche quelque chose de similaire à C# 's' ref 'mot-clé.'passe paramètre par référence' dans Ruby?

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 juste utiliser:

a = func(a) 

Répondre

30

Vous pouvez accomplir cela en passant explicitement dans la liaison actuelle:

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

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

Est-ce que ce fil est sûr? – Dex

18

Ruby ne supporte pas du tout "passer par référence". 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 à l'objet Fixnum par valeur.

Le problème avec votre code est que x += 1 ne modifie pas l'objet Fixnum transmis mais crée un objet complètement nouveau et indépendant.

Je pense que les programmeurs Java appellent Fixnum les objets immutables.

+3

Je ne comprends pas ce que Ruby ne passe pas par ref, quand les variables et les paramètres ne peuvent contenir que des références aux objets. Dire que les références sont passées par valeur revient à dire que les objets sont passés par référence. –

+2

@Damien: non ce n'est pas le cas. Passer par référence (par exemple, en C++, C#, PHP, Perl) vous permet de * affecter * à la variable comme si vous lui étiez assigné dans la portée externe. Ce que vous essayez de faire ici serait possible avec un vrai passage par référence; mais pas avec le passage par la valeur des références. – newacct

+6

Vous avez raison, je lis la réponse de Christoph et mon commentaire à nouveau et je ne suis pas d'accord avec mon auto-2009. Hmm ... –

10

Dans Ruby vous ne pouvez pas passer des 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 
6

Vous pouvez essayer de suivre astuce:

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' 
+0

oui, cela fonctionne –

+0

Techniquement, cela remplace aussi la variable (et la référence dans la liste) en écriture. – itarato

Questions connexes