2016-03-24 3 views
24
def foo(_, _='override') 
    _ 
end 

p foo("bye bye") 
p foo("hello", "world") 

Sortie:Quelle est la logique derrière ce résultat?

"override" 
"hello" 

Je comprendrais si le résultat était:

"override" 
"world" 

ou même:

"bye bye" 
"hello" 

Mais le résultat que je suis en train de me cause de la confusion.

+1

Je ne pense pas que votre ajout d'étiquette C est bon. La question concerne la mise en œuvre du cœur de Ruby, mais pas celle du langage C. – sawa

+0

Avis pris. J'ai retiré l'étiquette. – Gerry

+12

Underscore de Schrödinger – Stefan

Répondre

0

Une explication possible est que le nom _ signifie «variable inutilisée». Vous n'êtes même pas censé le référencer, encore moins en attendre des valeurs. Comme il s'agit d'un nom spécial, il reçoit un traitement spécial de la part de l'analyseur (comme la suppression des erreurs de "paramètres en double"). J'imagine que personne ne se souciait de faire que ce code produise un résultat logique, car, encore une fois, ce sont les variables non utilisées.

Si vous le renommez en autre chose (par exemple, a), vous obtiendrez une erreur, car cette signature de méthode n'a plus aucun sens.

+1

Cela ne répond pas à la question. – sawa

+0

@sawa: que diriez-vous? –

+2

Je pense que tout le monde est d'accord pour dire que "_" ne devrait pas être mentionné dans un code de production. Mais il devrait y avoir une certaine logique derrière cela qui renvoie une valeur particulière. Je pense que le PO demande à ce sujet. Votre réponse n'est pas fausse, mais ne répond toujours pas à la question. – sawa

1

Ican't trouver une meilleure explication que celle-ci

ruby magic underscore

La raison se trouve dans l'analyseur de Ruby, en shadowing_lvar_gen. Toutes les vérifications normales pour la duplication sont ignorées si le nom de la variable est constitué d'un seul trait de soulignement.

+2

+ 1 pour quelques infos intéressantes que je n'ai pas réalisé à propos de la cession destructuring. Cependant, l'article ne traite pas de mon problème, alors il semble que vous me dites de "lire la source"? :) – Gerry

+0

Ce comportement a été étendu dans 2.0.0 en autorisant uniquement un trait de soulignement pour permettre à toutes les variables commençant par un trait de soulignement d'avoir des noms en double. En outre, le lien correct vers la source (1.9.3) [est ce] (https://github.com/ruby/ruby/blob/ruby_1_9_3/parse.y#L8474). – Carpetsmoker

+2

Cela ne répond pas du tout à la question. – sawa

4

Les arguments par défaut sont évalués plus tôt dans le temps que les arguments normaux si un argument est passé, sinon ils sont évalués en dernier. Presque certain mais incertain comment le prouver.

Signification dans cet exemple:

au temps 0 appel p foo("hello", "world")

au temps 1 _ = 'override'

au temps 2 _ = "world"

au moment 3 _ = "hello"

au moment de 4 variables sont imprimés et vous voyez "bonjour"

EDIT voici quelques preuves:

def foo(_, _='override',_) 
    _ 
end 

p foo("bye bye","goodbye") 
p foo("hello", "world", "three") 

impressions

"override" 
"three" 
+1

Puisque vous avez "sinon", le "et seulement si" est redondant. – sawa

+1

Bon point, le "sinon" était une sorte de réflexion après coup mais je vais le réparer. EDIT oups vous l'avez déjà corrigé. –

+0

Dans votre chronologie de commande, l'affectation est par défaut, arg2, arg1. Cependant, dans votre deuxième exemple, quel est l'ordre proposé? par défaut, arg2, arg1, arg3? (Pour les trois premiers, j'utilise l'ordre de votre timeline). – Gerry