Ich kam auf diese Frage, als ich versuchte, dies zu beantworten . Folgendes ist ein erwartetes Verhalten:
%Vor%Aber das Folgende:
%Vor% all return []
. Warum funktionieren diese nicht wie oben?
Zusätzliche Frage
Mu ist zu kurz, schlug einen interessanten Punkt vor. Wenn das richtig ist, dann wäre Module.nesting
eine der Methoden und Variablen, die vom literalen Kontext abhängen, wie Method#source_location
, __FILE__
. Ist dieses Verständnis korrekt? Wenn ja, kann jemand das Inventar dieser Methoden / Variablen bereitstellen, die vom wörtlichen Kontext abhängig sind? Ich denke, es wäre nützlich als Referenz.
Warnung : Das ist ein bisschen lang. Ein bisschen eine Tour durch den Ruby-Quellcode scheint notwendig, da die Dokumentation ein wenig dünn ist. Fühlen Sie sich frei, zum Ende zu springen, wenn Sie sich nicht dafür interessieren, wie Wurst gemacht wird.
Der 1.9.2 Module.nesting
ist in eval.c
wie folgt implementiert:
Ich kenne die Ruby-Interna nicht gut, aber ich lese die while
-Schleife wie folgt: Extrahiere aus der verknüpften Liste cref
alle Knoten, die mit einer klassenähnlichen Sache verbunden sind, aber nicht von ihr kommen %Code%. Das eval
-Bit wird nur hier gesetzt:
Ein bisschen mehr Greife und Lesen zeigt, dass NODE_FL_CREF_PUSHED_BY_EVAL
am Ende durch instance_eval
geht. Ich überlasse die Überprüfung von yield_under
, instance_exec
und module_eval
als Übungen für den Leser. In jedem Fall scheint module_exec
explizit aus der instance_eval
-Liste ausgeschlossen zu sein; Dies ist jedoch eher eine Ablenkung als alles andere, es bedeutet nur, dass Sie etwas nicht sehen, was die evals erwähnt.
Nun ist die Frage "Was sind Module.nesting
und NODE
alles?".
Wenn Sie in rb_vm_cref()
suchen, sehen Sie eine Reihe von NODE-Konstanten für die verschiedenen Ruby-Schlüsselwörter und Sprachstrukturen:
node.h
NODE_BLOCK
NODE_BREAK
NODE_CLASS
NODE_MODULE
also würde ich vermuten, dass NODE_DSYM
ein Knoten im Befehlsbaum ist. Das passt gut zu meinem
NODE
scheint mehr über das Sprechen mit dem Parser zu sein
Vermutung im Kommentar. Aber wir werden trotzdem weitermachen.
Die Funktion Module.nesting
ist nur ein Wrapper für rb_vm_cref
, der ein Wrapper für vm_get_cref
ist. Worum geht es in vm_get_cref0
? Es geht darum:
Alle drei Argumente für die Funktion stammen direkt aus diesem Steuerrahmen:
%Vor% Die vm_get_cref0
scheint eine Befehlssequenz zu sein und die iseq
und lfp
sind Rahmenzeiger:
Die Definition von dfp
ist relevant:
Es sieht also so aus, als ob Sie aus cref_stack
eine Art Aufruf- oder Schachtelungsstapel bekommen.
Nun zurück zu den Einzelheiten. Wenn Sie dies tun:
%Vor% Sie haben rb_vm_cref
in der verknüpften Liste module A
(die gefiltert wird, um das Array cref
result zu erzeugen), da Sie noch nicht Module.nesting
getroffen haben. Wenn Sie diese sagen:
Sie werden end
in module A
nicht mehr haben, weil Sie bereits cref
popped end
vom Stapel entfernt haben. Wenn Sie dies jedoch tun:
Sie sehen diese Ausgabe:
%Vor%, weil die module A
noch nicht geschlossen (und von module A
entfernt) wurde.
Zum Schluss sagt die cref
-Dokumentation Folgendes:
Gibt die Liste der verschachtelten Module zurück.
Ich denke, diese Aussage zusammen mit der Überprüfung der Interna zeigt an, dass Module.nesting
tatsächlich von dem spezifischen wörtlichen Zusammenhang abhängt, in dem es aufgerufen wird.
Wenn jemand mit mehr Erfahrung im Ruby-Internal etwas hinzuzufügen hat, kann ich dies der SO-Community als Community-Wiki übergeben.
UPDATE : Dies gilt sowohl für Module.nesting
als auch für class_eval
und gilt auch für 1.9.3 genauso wie für 1.9.2.