Réimprimé de Article de blog.
Récemment, j'ai écrit quelques personnes qui en sont accro, je vais donc le résumer un instant.
Dans Ruby, lors de l'appel d'une méthode, vous pouvez "appeler la méthode en omettant` ()" "par rapport aux autres langages.
def hoge(a = nil)
"#hoge(#{a})"
end
#Vous pouvez appeler une méthode sans parenthèses
p hoge
# => "#hoge()"
#Vous pouvez faire référence à la méthode même avec un appel de type méthode
p hoge() # => "#hoge()"
p hoge 42 # => "#hoge(42)"
p self.hoge # => "#hoge()"
Eh bien c'est vrai.
Le problème est lorsque «méthodes et variables du même nom» sont mélangées. Dans ce cas, reportez-vous à la méthode "Variable si la variable peut être référencée" et "Sinon".
def hoge(a = nil)
"#hoge(#{a})"
end
#Puisqu'aucune variable n'est définie à ce stade, la méthode est appelée avec priorité.
p hoge # => #hoge()
#Définir des variables
hoge = 42
#Après avoir défini la variable, donnez la priorité à la variable.
p hoge # => 42
#Dans un appel de type méthode, appelez la méthode
p hoge() # => "#hoge()"
p hoge 42 # => "#hoge(42)"
p self.hoge # => "#hoge()"
À ce stade, notez que "méthode si avant l'expression d'affectation" et "variable si avant l'expression d'affectation".
Par exemple, dans Ruby, il y a un cas où le processus qui définit réellement la variable n'est pas appelé comme suit.
def hoge(a = nil)
"#hoge(#{a})"
end
if false
hoge = 42
end
#Est-ce une référence de méthode?
p hoge
Dans le langage d'interprétation, on peut s'attendre à ce que ce soit "la méthode est appelée parce que la variable n'est pas définie".
Cependant, en réalité, «p hoge» fait référence à la «variable« hoge »».
C'est un secret sur la façon dont Ruby exécute le code source.
Dans Ruby, avant d'exécuter le code source, commencez par «analyser l'intégralité du code source Ruby», puis exécutez le code Ruby.
Ainsi, comme le code ci-dessus, la variable hoge
est implicite lorsque" l'expression d'affectation "est définie car tout le code source est analysé indépendamment de" si le code est appelé à l'exécution ". Il sera défini dans.
Par conséquent, indépendamment du fait que le contenu de l'instruction if soit réellement appelé, la "variable hoge
" sera référencée "en dehors de l'instruction if" lorsque "l'expression d'affectation" est définie.
#Résultat d'exécution réel
def hoge(a = nil)
"#hoge(#{a})"
end
if false
hoge = 42
end
#Variables de référence ici
#Renvoie nil car la valeur par défaut de la variable est nil
p hoge
# nil
Il est très difficile de comprendre comment Ruby analyse le code source.
Par exemple, que se passe-t-il si vous "définissez une variable hoge
en faisant référence à hoge
avec un suffixe if "comme suit?
hoge = 42 if hoge.nil?
p hoge
Beaucoup de gens pensent que c'est parce que ʻif hoge.nil? Est traité avant la définition de variable, donc le processus
hoge = 42n'est pas réellement appelé. Cependant, en réalité, le code
hoge = 42 if hoge.nil?Est analysé comme "ceci est un processus au total". Par conséquent, quand ʻif hoge.nil?
Est appelé, le code hoge = 42
a déjà été analysé et le processus est "la variable" hoge` est définie ".
Ainsi, le résultat de l'exécution du code ci-dessus est
hoge = 42 if hoge.nil?
p hoge
# => 42
Ensuite, " hoge = 42
"est traité.
Par contre, s'il ne s'agit pas d'un suffixe if, le résultat sera différent, il faut donc faire attention.
#Cela entraînera une erreur
# error: undefined local variable or method `hoge' for main:Object (NameError)
if hoge.nil?
hoge = 42
end
C'est parce que ʻif hoge.nil? `Est analysé avant la variable et l'expression conditionnelle de l'instruction if est exécutée" dans l'état où la variable n'est pas définie ".
Dans Ruby, il existe une méthode appelée «eval». C'est la méthode qui exécute le code source Ruby "au moment de l'exécution".
def hoge(a = nil)
"#hoge(#{a})"
end
hoge = 42
#Exécutez la chaîne transmise à eval en tant que code Ruby
p eval("hoge + hoge")
# => 84
Lorsque le code ci-dessus est exécuté, «hoge + hoge» est exécuté après l'expression d'affectation, donc reportez-vous à «Variable». Alors, que se passe-t-il lorsque vous exécutez du code comme celui-ci:
def hoge(a = nil)
"#hoge(#{a})"
end
#Exécuter hoge avant l'expression d'affectation
p eval("hoge")
hoge = 42
D'après le flux expliqué plus haut, "j'exécute" "hoge" "avant la variable", donc je m'attends à ce que ce soit un "appel de méthode". Cependant, lorsqu'il est réellement exécuté, le résultat est le suivant.
def hoge(a = nil)
"#hoge(#{a})"
end
#Faire référence à des variables au lieu d'appels de méthode
p eval("hoge")
# => nil
hoge = 42
La raison de ce résultat est que "le timing du code source Ruby" et "le timing de l'exécution de ʻeval" sont différents. Le moment d'exécution de ʻeval
est "au moment de l'exécution de Ruby".
Ce "runtime" est "après que le code source de Ruby a été analysé".
En d'autres termes, puisque "le moment d'exécution de ʻeval" "est déjà" après que le code source de Ruby a été analysé ", l'expression" hoge "se réfère à" avec priorité donnée aux variables ". Par conséquent, lors du référencement d'une variable ou d'une méthode à partir de ʻeval
, la "variable" est préférentiellement appelée indépendamment de la "position de définition de l'expression d'affectation".
Cela affecte également l'utilisation de binding.irb
, ce qui pose un problème lors de l'appel de binding.irb
" avant l'expression d'affectation ", par exemple:
def hoge(a = nil)
"#hoge(#{a})"
end
#Liaison pour le débogage, etc..Démarrez irb à l'exécution avec irb
#Si vous faites référence à hoge sur cette console irb, vous verrez des "variables".
binding.irb
hoge = 42
binding.irb
exécute le code Ruby entré en utilisant ʻeval. Par conséquent, il sera exécuté en se référant à la "variable" comme dans l'exemple précédent. Je pense qu'il est rare d'utiliser ʻeval
dans le code Ruby normal, mais vous devez être prudent car utiliser binding.irb
etc. signifie indirectement utiliser ʻeval`. ..
hoge
"est un appel de méthode ou une référence de variable.ou
binding.irb`J'ai donc essayé de résumer les variables Ruby.
Lorsque vous appelez une méthode avec binding.irb
, nil
peut être retourné, et si vous regardez attentivement le code, un nom de variable avec le même nom est défini après binding.irb
. Il y avait une chose.
Comme vous pouvez le voir, il y a quelques points addictifs dans Ruby, alors soyez prudent.
Recommended Posts