Je travaille avec Ruby Koans.
Le test_the_shovel_operator_modifies_the_original_string
Koan dans about_strings.rb comprend le commentaire suivant:
Les programmeurs Ruby ont tendance à préférer l'opérateur de pelle (<<) à l'opérateur plus égal (+ =) lors de la création de chaînes. Pourquoi?
Je suppose que cela implique de la vitesse, mais je ne comprends pas l'action sous le capot qui ferait que l'opérateur de la pelle serait plus rapide.
Quelqu'un pourrait-il expliquer les détails de cette préférence?
ruby
string
optimization
Erinbrown
la source
la source
Réponses:
Preuve:
<<
Modifie donc la chaîne d'origine plutôt que d'en créer une nouvelle. La raison en est que dans rubya += b
est un raccourci syntaxique poura = a + b
(il en va de même pour les autres<op>=
opérateurs) qui est une affectation. D'autre part,<<
un aliasconcat()
modifie le récepteur en place.la source
Array#join
c'est plus lent que d'utiliser<<
.Preuve de performance:
la source
Un ami qui apprend Ruby comme son premier langage de programmation m'a posé la même question en parcourant Strings in Ruby sur la série Ruby Koans. Je lui ai expliqué en utilisant l'analogie suivante;
Vous avez un verre d'eau à moitié plein et vous devez remplir votre verre.
Tout d'abord, prenez un nouveau verre, remplissez-le à moitié avec de l'eau du robinet, puis utilisez ce deuxième verre à moitié plein pour remplir votre verre à boire. Vous faites cela chaque fois que vous devez remplir votre verre.
La deuxième façon de prendre votre verre à moitié plein et de le remplir avec de l'eau directement du robinet.
À la fin de la journée, vous auriez plus de verres à nettoyer si vous choisissez de choisir un nouveau verre chaque fois que vous avez besoin de remplir votre verre.
Il en va de même pour l'opérateur de la pelle et l'opérateur plus égal. De plus, l'opérateur égal choisit un nouveau `` verre '' chaque fois qu'il a besoin de remplir son verre tandis que l'opérateur de la pelle prend juste le même verre et le remplit. À la fin de la journée, plus de collection de «verre» pour l'opérateur Plus égal.
la source
C'est une vieille question, mais je viens de la parcourir et je ne suis pas entièrement satisfait des réponses existantes. Il y a beaucoup de bons points à propos de la pelle << étant plus rapide que la concaténation + =, mais il y a aussi une considération sémantique.
La réponse acceptée de @noodl montre que << modifie l'objet existant en place, alors que + = crée un nouvel objet. Vous devez donc déterminer si vous souhaitez que toutes les références à la chaîne reflètent la nouvelle valeur ou si vous souhaitez laisser les références existantes seules et créer une nouvelle valeur de chaîne à utiliser localement. Si vous avez besoin que toutes les références reflètent la valeur mise à jour, vous devez utiliser <<. Si vous souhaitez laisser les autres références seules, vous devez utiliser + =.
Un cas très courant est qu'il n'y a qu'une seule référence à la chaîne. Dans ce cas, la différence sémantique n'a pas d'importance et il est naturel de préférer << à cause de sa rapidité.
la source
Parce que c'est plus rapide / ne crée pas de copie de la chaîne <-> garbage collector n'a pas besoin de s'exécuter.
la source
malloc
/free
. En outre, certaines implémentations Ruby plus modernes optimiseront probablement l'allocation d'objets et la concaténation de chaînes complètement. OTOH, la mutation des objets est terrible pour les performances du GC.Bien que la couverture de la majorité des réponses
+=
soit plus lente car elle crée une nouvelle copie, il est important de garder à l'esprit cela+=
et<<
ne le sont pas interchangeables! Vous souhaitez utiliser chacun dans des cas différents.L'utilisation
<<
modifiera également toutes les variables pointéesb
. Ici, nous muterons égalementa
lorsque nous ne le voulons pas.Parce que
+=
fait une nouvelle copie, il laisse également toutes les variables qui pointent vers lui inchangées.Comprendre cette distinction peut vous éviter beaucoup de maux de tête lorsque vous avez affaire à des boucles!
la source
Bien que ce ne soit pas une réponse directe à votre question, pourquoi The Fully Upturned Bin a toujours été l'un de mes articles Ruby préférés. Il contient également des informations sur les chaînes concernant le garbage collection.
la source