Wie wird proc ausgeführt, wenn es an 'instance_exec' übergeben wird

9

Die Frage ist inspiriert von diesem .

Proc::new hat eine Option, die ohne einen Block innerhalb einer Methode aufgerufen werden kann:

  

Proc::new darf ohne einen Block nur innerhalb einer Methode mit angehängtem Block aufgerufen werden. In diesem Fall wird dieser Block in das Objekt Proc konvertiert.

Wenn die Instanz proc / lambda als Codeblock übergeben wird, wird die neue Instanz von Proc erstellt:

%Vor%

Wie man sehen kann, ist weder der Aufruf von Proc::new noch Proc#initialize und / oder Proc#call aufgerufen worden.

Die Frage ist: wie Ruby einen Block Wrapper unter der Haube erstellt und ausführt?

NB Testen Sie den obigen Code nicht in pry / irb console: Sie wissen, dass sie Fehler bei der puren Ausführung haben, im Grunde, weil sie Patches proced.

    
mudasobwa 22.11.2016, 10:28
quelle

1 Antwort

2

Es gibt einige Diskussionen über dieses Verhalten im Ruby Issue Tracker, siehe Feature # 10499: Eliminiere implizite Magie in Proc.new und Kernel#proc .

Dies ist ein Implementierungsartefakt von YARV: YARV schiebt einen Block auf den globalen VM-Stack und Proc::new erstellt einfach einen Proc vom obersten Block auf dem Stack. Also, wenn Sie Proc.new aus einer Methode heraus aufrufen, die mit einem Block aufgerufen wurde, greift es gerne den Block, der sich oben auf dem Stapel befindet, ohne zu überprüfen, woher er kommt. Irgendwie, irgendwo im Nebel der Zeit, wurde dieses (zufällige) Artefakt (ich würde es eigentlich eher einen Fehler nennen) zu einem dokumentierten Feature. Ein Feature, das die Entwickler von JRuby (und vermutlich Rubinius, Opal, MagLev, etc.) lieber loswerden würden.

Da die meisten anderen Implementierungen völlig anders funktionieren, macht dieses Verhalten, das "kostenlos" auf YARV kommt, sowohl Blöcke als auch% auf andere Implementierungen teurer und verbietet mögliche Optimierungen (was auf YARV nicht schadet, weil YARV optimiert nicht).

    
Jörg W Mittag 26.11.2016 18:20
quelle

Tags und Links