Hi.
Imagine I have method a: and I want to skip the execution (return self or nil or whatever) when a: is evaluated with parameter 0. I have tried to add a meta link which will run instead of the method with a condition, but the condition did not work… I have tried to implement the metallic method to do nothing if the arg is 0 otherwise to perform the method, but I end up with an infinite loop… Did anybody do something like that already? Any suggestions? Uko
|
I’ve also described the question with examples on SO: https://stackoverflow.com/questions/40200546/conditionally-skip-a-method-with-matalinks
|
I was looking at this and ran into some very odd behavior:
imagine we have some method: ``` Object subclass: #MyClass. MyClass compile: 'method: arg Transcript crShow: ''executed '', arg asString'. ``` and a simple metalink ``` link := MetaLink new metaObject: Halt; selector: #now; control: #instead. (MyClass >> #method:) ast link: link. ``` Now I can do the following to execute the code: ``` c := MyClass new. (MyClass>>#method:) valueWithReceiver: c arguments: #(1). (MyClass>>#method:) reflectiveMethod valueWithReceiver: c arguments: #(1). (MyClass>>#method:) compiledMethod valueWithReceiver: c arguments: #(1). MyClass rFwithArgs: #(1) executeMethod: (MyClass>>#method:) compiledMethod. ``` All of the statements above will call the method WITHOUT triggering the metalink, which is odd. Now what's even stranger, if I instead do this ``` c := MyClass new. c method: 1. (MyClass>>#method:) valueWithReceiver: c arguments: #(1). (MyClass>>#method:) reflectiveMethod valueWithReceiver: c arguments: #(1). (MyClass>>#method:) compiledMethod valueWithReceiver: c arguments: #(1). MyClass rFwithArgs: #(1) executeMethod: (MyClass>>#method:) compiledMethod. ``` Then ALL the statements (starting with `c method: 1`) will be suddenly halting (triggering the metalinks). So my questions are: 1) why in the first case the following two methods didn't trigger the metalink? (MyClass>>#method:) valueWithReceiver: c arguments: #(1). (MyClass>>#method:) reflectiveMethod valueWithReceiver: c arguments: #(1). 2) why in the second case these two methods did trigger the metalink? (MyClass>>#method:) compiledMethod valueWithReceiver: c arguments: #(1). MyClass rFwithArgs: #(1) executeMethod: (MyClass>>#method:) compiledMethod. #rFwithArgs:executeMethod: even has comment "This method is used by reflectivity internally. All meta-links are ignored". 3) why the class of (MyClass>>#method:) changed after calling `method:`? ``` (MyClass >> #method:) ast link: link. c := MyClass new. (MyClass>>#method:) class. "ReflectiveMethod" (MyClass>>#method:) valueWithReceiver: c arguments: #(1). (MyClass>>#method:) class. "ReflectiveMethod" c method: 1. (MyClass>>#method:) class. "CompiledMethod" ``` 4) (unrelated to the above) I tried calling `link disable` from within the #metaObject, but it was ignored, but maybe I don't understand its purpose. Thanks, Peter On Sun, Oct 23, 2016 at 09:21:59AM +0200, Yuriy Tymchuk wrote: > I’ve also described the question with examples on SO: https://stackoverflow.com/questions/40200546/conditionally-skip-a-method-with-matalinks > > > On 22 Oct 2016, at 23:13, Yuriy Tymchuk <[hidden email]> wrote: > > > > Hi. > > > > Imagine I have method a: and I want to skip the execution (return self or nil or whatever) when a: is evaluated with parameter 0. I have tried to add a meta link which will run instead of the method with a condition, but the condition did not work… I have tried to implement the metallic method to do nothing if the arg is 0 otherwise to perform the method, but I end up with an infinite loop… > > > > Did anybody do something like that already? Any suggestions? > > > > Uko > |
In reply to this post by Uko2
Hi,
i would be also interested in answer to this interesting MetaLink-question. werner p.s. Yuriy, i guess this could also be done with ghost On 10/23/2016 09:21 AM, Yuriy Tymchuk wrote:
|
In reply to this post by Peter Uhnak
2016-10-23 12:15 GMT+02:00 Peter Uhnak <[hidden email]>: I was looking at this and ran into some very odd behavior: There is only one way to "compile and install" the modified method and unless this is done, all the above messages are received on the ReflectiveMethod and delegated to the CompiledMethod (see ReflectiveMethod>>##doesNotUnderstand: All of the statements above will call the method WITHOUT triggering the metalink, which is odd. by the first call "c method:1" this is the place where the ReflectiveMethod actually compiles and installs a modified compiled method. the magic happens with "objects as methods" and the method run:with:in: (if the vm looks up a message send, and the object in the method dictionary is *not* a CompiledMethod, it calls the object with the method run: aSelector with: anArray in: aReceiver This is implemented in ReflectiveMethod and will actually compile and install the new CompiledMethod. Then ALL the statements (starting with `c method: 1`) will be suddenly halting (triggering the metalinks). Yes because the compiled method to be called is now the new one. (MyClass>>#method:) class -> " this is now a compiled method again, but the new, modified one".
You can enable / disable the condition without actually changing / reinstalling the link link condition:[:args | args first isNumber] arguments:#(arguments). c method:1. "<- will trigger halt" c method:'s'. "<- wont trigger halt" link disable. "<- disable the condition, like condition never holds" c method:1. "<- wont trigger halt" c method:'s'. "<- wont trigger halt"
|
In reply to this post by Uko2
Am 23.10.2016 9:22 vorm. schrieb "Yuriy Tymchuk" <[hidden email]>: Answered on SO. >> On 22 Oct 2016, at 23:13, Yuriy Tymchuk <[hidden email]> wrote: |
Free forum by Nabble | Edit this page |