2010-04-16 24 views
2

Comme un moyen de pimenter mes devoirs de programmation C++, j'ai décidé de ne pas taper le C++ du livre sur mon ordinateur, au lieu de le reformer dans Ruby. Oui c'est un peu idiot, mais je m'ennuie.void foo (int & x) -> Ruby? Passer des entiers par référence?

Quoi qu'il en soit, je vais avoir du mal à convertir ce genre de fonction Ruby

void swap(int &a,int &b){ 
    int c=b; 
    b=a; 
    a=c 
} 

Quel serait le code rubis équivalent dans une fonction?

Répondre

6

Ruby est passe par valeur strictement. Toujours. Mais parfois ces valeurs sont des poointers.

est ici quelques liens:

Notez que si tous ces disent "Java", ils devraient vraiment dire "Smalltalk et ses descendants", qui inclut Jav a, Ruby et une tonne d'autres langues.

Je pense que la plupart de la confusion provient de deux problèmes:

  1. Ruby références de laissez-passer par valeur. Mais le mot "référence" dans cette phrase n'est pas le même que le mot "référence" dans "passer-par-référence". Peut-être est-il plus clair lorsque nous désambiguïsons: remplaçons «pass-by-reference» par «pass-by-variable» et «reference» par «pointer» (notons que ce sont de bons «bons» poointers, pas les «mauvais» "celles de C):
    • Fortran est le passage par la variable
    • Ruby est le passage par la valeur et les valeurs qu'elle passe sont pour la plupart poointers
  2. les références (poointers) que Ruby de laissez-passer pointer vers des objets mutables. Par conséquent, alors que vous ne pouvez pas modifier la référence, vous pouvez muter les objets vers lesquels pointe la référence. Le problème ici est que Ruby (comme la plupart des langages orientés objet impératifs) confond les concepts d'identité, d'état et de valeur.Vous pouvez en apprendre davantage sur ce problème et comment le résoudre ici (Notez que pendant qu'ils disent « Clojure », les concepts qui sont présentés sont universels et peuvent être appliquées aussi bien à OO):

BTW: Je délibérément mal orthographié « poointers » avec un OO pour l'orientation objet pour préciser que je ne parle pas des adresses mémoire premières, je parle de références opaques à des objets (et évident raisons pour lesquelles je ne veux pas utiliser le mot "référence" ; Si vous connaissez un meilleur mot qui n'est ni "pointeur" ni "référence", j'aimerais l'entendre).

+0

Apparemment, c'est largement discutable http://www.ruby-forum.com/topic/41160 – Earlz

+0

Il est vrai dans, de la même manière que Java et Javascript sont passés par la valeur. –

+0

@Earlz: c'est juste un désaccord sur la terminologie entre les différentes communautés linguistiques. les objets en Java se comportent de la même manière, et ils l'appellent valeur par échange – newacct

1

Dans Ruby, les arguments sont passés par valeur. Ainsi, la méthode suivante aura jamais d'effet:

def doesnt_swap(a, b) 
    c = a 
    a = b 
    b = c 
end 

D'autre part, les objets mosts sont des références, pour les chaînes d'exemples, vous pouvez donc écrire

def swap_strings(a, b) 
    c = a.dup 
    a.replace(b) 
    b.replace(c) 
end 

Cette échangeraient les valeurs de chaîne de la deux arguments.

Les nombres entiers sont des nombres instantanés, donc il n'y a pas d'équivalent à replace; vous ne pouvez pas écrire swap_integers.

Quoi qu'il en soit, Ruby, vous échangez en écrivant a, b = b, a

+1

N'y a-t-il pas moyen de "boxer" des entiers ou quelque chose comme ça pour le forcer à passer par référence? – Earlz

+0

@Earlz: Si les entiers sont membres d'un objet, vous pouvez échanger les valeurs des variables d'instance de l'objet. Vous ne pouvez pas accéder aux variables locales dans une autre étendue. – Chuck

+0

@Earlz: Eh bien, il y a (en utilisant un SimpleDelegator), mais vous ne verrez jamais cela dans Ruby. –