TruerWords Logo

Search TruerWords

Sign Up  Log On

Optimize Your UserTalk Code: Remove Extra Variables

Optimize Your UserTalk: Remove Extra Variables

When optimizing UserTalk code, one thing to watch for is the use of extra variables (this actually applies to all languages, though most have built-in optimizers that take care of this for you). Every variable creation and assignment operation uses a little processor time.

One common "extra variable" seen in lots of UserTalk scripts is where you call one script to get a value, assign that value to a variable, and then only use that variable once: either return it, or just pass it along to another script, like this:

local ( foo = getAValue() );
return doSomething( foo )

A more efficient form is just:

return doSomething( getAValue() )

Unfortunately, there's a circumstance where you can't do that. Let's look at a slightly more complex example:

Create a new script and paste the following in, then run it. It SHOULD return true, every time. Instead, it always returns false.

on b() {
	try {
		ScriptError( "Sorry charlie." )}
	else {
		return @workspace}};
on a() {
	msg( defined( b()^ ) )};

Step through it, watch what happens.

A() calls B() from within a defined() statement. B() traps all errors with a try/else block, and then throws an error from within the try statement. (This is a simplified example of a real-world case, where B() actually called another script which returned an error.)

The error should be trapped by B(), passing control into the else block, but instead control returns to A()'s defined() statement, which returns false. The else block in B() is never run.

Somehow, the implicit error trapping built into the defined() statement is overriding the explicit error trapping in B().

Here's a version that works as intended, but is less efficient because it takes an extra step and uses an extra variable:

on b() {
	try {
		ScriptError( "Sorry charlie." )}
	else {
		return @workspace}};
on a() {
	local ( adr = b() );
	msg( defined( adr^ ) )};

Now that the call to B() has been taken out of the defined() statement in A(), the else block in B() is allowed to run.

It's a very confusing bug in the UserTalk interpreter built into Radio and Frontier, but knowing about it ahead of time will, I hope, make a big difference.

To boil it down, here are two general rules:

  • Avoid single-use variables. Whenever possible, pass values directly from one script call into another, instead of assigning the result of a call to a local variable and then passing that variable to another script.

  • Watch out for implicit error trapping in defined(). If you're calling a script to get an address and passing it's result to the defined() statement, and there's any chance that the script could return an error, you MUST assign the result of the script to a variable and then call defined with that variable. (As demonstrated above.)

Page last updated: 5/2/2003

is Seth Dillingham's
personal web site.
More than the sum of my parts.