On NewtonScript's Perform() ¬
2012-08-05
I’ve been playing with NewtonScript a bit in what little spare time I have, hence the previous posts on the subject. The eventual plan, of course, is to put together a few new packages for my MessagePad 2100, maybe even something useful to others, but in the meantime I just want to get comfortable with the language. For that, I’ve found playing with NEWT/0 to be the easiest, but, while the core is there, a number of the built-in functions are still missing.
One such function was Perform()
, which allows dynamically sending a message to a frame. I say was because, with Makoto Nukui (NEWT/0’s developer) pointing (and re-pointing) me in the right direction, I was able to implement all the message sending global functions, namely: Apply()
, Perform()
, PerformIfDefined()
, ProtoPerform()
, and ProtoPerformIfDefined()
. All of which have been merged back to master, so they’re at your disposal if you build newt
from the latest source.
No need to go into details on the implementation, the functionality was already there and just needed to be wrapped around, but I did want to discuss usage of Perform()
. I won’t cover its variants as they’re called the same way, they just allow silent failures (in the case of *IfDefined()
) or different inheritance searching (in the case of Proto*()
).
As I mentioned above, Perform()
allows you to more dynamically send a message to a frame. For example, let’s take the following frame which has a Test()
method:
someFrame := {
Test: func () begin
Print("Hello world.\n");
end
};
Normally, if we wanted to send the someFrame
frame a message of Test
, we’d do so as follows:
someFrame:Test();
And it would execute the Test
method, outputting:
Hello world.
Well, what if you didn’t know until runtime how many arguments you should need to pass along with message you’re sending? That’s where Perform
comes in. It takes three arguments: the frame you want to send the message to, a symbol denoting which method should be called, and an array of parameters to send to said method (or nil
if not passing any arguments). So, building on our previous example, like so:
Perform(someFrame, 'Test, nil);
Or, if one were passing parameters along with the message:
Perform(someOtherFrame, 'SomeOtherMethod, ["parameter 1", 2]);
Note the use of the quoted constant, 'Test
& 'SomeOtherMethod
, naming the method to be called. What if you also didn’t know the name of the method until runtime? How can you convert a string to a symbol to pass to Perform()
? Fortunately, there’s Intern()
, which returns a symbol when passed a string. With that, we can fully dynamically send a message to a frame, as follows:
methodName := "Test";
Perform(someFrame, Intern(methodName), nil);
This is all documented in The NewtonScript Programming Language (PDF; mirrors: UNNA, Newted), but it’s spread out a bit, so figured I’d summarize it all in one place. I’d love to see others start playing with NewtonScript more as well.