I'm trying to understand the method "withArgs: executeMethod: " in smalltalk, squeak.
1. I am trying to understand what is the role of the method? 2. What arguments need to be passed to it for it to be carried out?
I'm trying to understand the method "withArgs: executeMethod: " in smalltalk, squeak.
1. I am trying to understand what is the role of the method? 2. What arguments need to be passed to it for it to be carried out?
Copyright © 2021 Jogjafile Inc.
A good way to understand this method is by considering it as a syntactic variant of the general expression
where
objectis the receiver of the message with selectormsg:andargits argument. There are of course variants with no or multiple arguments, but the idea is the same.When
objectreceives this message (*) the Virtual Machine (VM) looks up for theCompiledMethodwith selectormsg:in theobject's hierarchy, and transfers it the control, bindingselftoobjectand the formal argument of the method toarg.Notice that this invocation is managed by the VM, no by the Virtual Image (VI). So, how could we reflect the same in the VI? Well, there are two steps in this behavior (1) find the method and (2) bind its formal receiver and arguments to the actual ones and let it run.
Step (1) is the so called lookup algorithm. It is easily implemented in Smalltalk: just ask the receiver its class, check whether the class includes the selector
#msg:and, if not, go to the superclass and repeat. If all checks fail, issue thedoesNotUnderstand:message.Step (2) exactly requires what
#withArgs:executeMethod:provides. It allows us to saywhere
methodis theCompiledMethodfound in step (1). [We have to use{arg}rather thanargbecause the plural inwithArgs:suggests that the method expects anArrayof arguments.]Why would we want this?
Generally speaking, giving the VI the capability to mimic behavior implemented in the VM is good because it makes metaprogramming easier (and more natural).
More practically, a relevant example of the use of this capability is the implementation of Method Wrappers. Briefly described, given any particular method, you can wrap it (as the
wrappee) inside awrappermethod, which also has apreBlock. If you then substitute the original method in theMethodDictionarywhere it belongs, with thewrapper, you can let thewrapperfirst execute thepreBlockand then the intended method. The first task is easy: just send the messagepreBlock value. For the second we have the method (thewrappee), the receiver and the arguments (if any). So, to complete the task you only need to send to the receiverwithArgs:executeMethod:with the actual argument(s) and thewrappee.Ah! Let's not forget to mention that one of the reasons for having Method Wrappers is to measure testing coverage.
Note also that
withArgs:executeMethod:does not require the second argument, i.e., the method to execute, to be in any class, let alone the class of the receiver. In particular, you could create aCompiledMethodon the fly and execute it on any given object. Of course, it is up to you to make sure that the execution will not crash the VM by, say, using the third ivar of the receiver if the receiver has only two etc. A simple way to create aCompiledMethodwithout installing it in any class is by asking the Smalltalk compiler to do so (look for senders ofnewCompilerto learn how to do that).