2016-10-23 7 views
1

Stellen wirBedingtes ein Verfahren mit METALINKS überspringen

MyClass>>#method: arg 

    Transcript crShow: 'executed' 

So eine Methode haben, wenn Sie MyClass new method: 1 tun das Transkript mit „ausgeführt“ Linien gefüllt ist.

Jetzt möchte ich diese Methode überspringen, wenn arg ist 0. Ich habe versucht, eine statt metalink mit einer Bedingung zu installieren:

link := MetaLink new 
    condition: [ :arguments | 
     arguments first = 0 ] 
    arguments: #(arguments); 
    control: #instead. 

(MyClass >> #method:) ast link: link 

Aber dann geht das Verfahren läuft nicht mehr, und ich möchte führen sie es, wenn die arg nicht 0

I habe auch den Zustand, in dem Metaobjekt auf diese Weise zu tun versucht:

link := MetaLink new 
    metaObject: [ :ast :arguments :receiver | 
     arguments first = 0 
     ifFalse: [ 
     ast compiledMethod 
      valueWithReceiver: receiver 
      arguments: arguments ] ]; 
    selector: #value:value:value:; 
    arguments: #(node arguments receiver); 
    control: #instead. 

(MyClass >> #method:) ast link: link 

Aber in diesem Fall enden Sie in einer unendlichen Rekursion, da der Metalink immer wieder aufgerufen wird, obwohl ich dachte, dass ast compiledMethod eine kompilierte Methode zurückgeben sollte und nicht das reflektierende Gegenstück

Antwort

1

ja, es sieht aus wie "statt hooks" werden immer "statt" der ursprünglichen Methode ausgeführt, selbst wenn die Verknüpfungsbedingung nicht erfüllt ist, der Unterschied besteht nur darin, ob wir den Wert der Link-Bewertung oder nur null zurückgeben.

Vielleicht sollte dies für stattdessen Links geändert werden.

Als Lösung für Ihre usecase, können Sie ein, bevor Link verwenden, die nur den Empfänger zurück, wenn die Bedingung erfüllt ist:

| ml | 
ml := MetaLink new. 
ml control: #before. 
ml condition:[:args | args first = 0] arguments:#(arguments). 
ml selector:#value:. 
ml metaObject:[:context | context return]. 
ml arguments:{#context}. 

(MyObject>>#method:) ast link:ml. 

die #context ist der Schlüssel für die thisContext refication (RFThisContextReification)