When the Going’s Not So Easy

by Dan Shafer

Browse. The lowest level of access to HyperCard.

All you can do if you’ve been relegated to the ranks of the “browsers,” is go from one card to another. Open a new stack. Go Home. Not much else. So, you’d think the go command would be the simplest, most straightforward word in the HyperTalk vocabulary. You’d be wrong. 

In recent weeks, my CompuServe friends and I have been talking about two interesting aspects of this often-used but not fully understood command. Some of the insights in this column are due to the explorations of Robert Wright and Brad Doster, but any inaccuracies are strictly my doing.

First, the go command is awfully picky about how you refer to cards to which you want it to travel. Second, if the go command fails inside a handler, you may not even be aware of the failure unless you do some explicit checking. 

Telling It Where to Go ∆ 

Let’s start with the simplest case. You write a HyperTalk command in a script that says, simply, go card 23. Assuming there are at least 23 cards in your stack, this command works fine. But try writing go card number 23 and you’ll be greeted by the message “Can’t understand arguments to command go.” You can’t use the phrase “card number” as any part of a destination for the go command, at least not any way we’ve been able to find.

You may be tempted, particularly if you’re aware of some of the other subtleties of HyperTalk that are now beginning to surface, to try surrounding parts of your addressing schemes with parentheses in an effort to force HyperTalk to evaluate terms in the intended order. But if you try typing go card (number 23) for example, the results are quite strange. (I’ll grant at the outset that this is perhaps a weird construct to ask HyperTalk to interpret. The phrase “number 23” is being treated as an expression and there’s no such HyperTalk command as number. Still, the results should be a bit more predictable, I think you’ll agree). The result of this attempted construct will be:

  • 1. An error dialog indicating that HyperTalk “can’t understand what’s after (.”
  • 2. After you dismiss that dialog, HyperTalk appears to attempt to display a standard get-file dialog (you know, one of those dialog boxes asking you to show HyperCard where something is). The part of the screen where such a dialog normally appears will go white, but then the process gets aborted somehow, and instead you get a message “No such card.”

I’m not sure we ought to characterize this behavior as “buggy,” after all we’ve done something pretty unexpected. On the other hand, HyperCard’s reaction is unpredictable and confusing.

Let’s try something a bit more complex. Sometimes we want to travel to a card whose identifier is contained in a variable. For example, if you put the value 23 into the variable targetCard and then try to go to that card, what will happen? You can do this from the Message Box:

put 23 into targetCard
go card targetCard

This works fine. You end up at card 23 of your stack. 

Let’s try putting the string “card 23” into the variable targetCard and seeing what the consequences are:

put “card 23” into targetCard
go targetCard

This will also work.

If you try using a computed expression as a card destination, though, you’ll encounter more problems. For example, computed expressions are often enclosed in parentheses to make sure HyperCard evaluates them the way we expect. But if you try something like:

go to card (add 3 to t2)

after putting a value like 23 into t2, you’ll get the same bizarre behavior. It seems as though we ought to be able to get HyperTalk to add a numeric value to a container containing a numeric value and then use the result in a go to statement, but no such luck. In fact, any attempt to use a computed expression inside parentheses directly in a HyperTalk command has problems. Try putting 23 into t2 and then typing put (add 3 to t2) in the Message Box. You’ll get an error message: “Can’t understand what’s after (.”

But if you do this same process in two stages:

add 3 to t2
go to card t2

it will work just fine.

This differs from the way most other programming languages handle computed branching statements. Those languages are branching to other statements in a program rather than traveling to some physical destination in an application, but the behavior still just doesn’t feel right to programmers with experience in other languages.

You can get similar results using the card id rather than the card number.

Where’d It Go? Nowhere! ∆ 

All these nuances would be of mere academic interest were it not for another interesting problem. If you carry out the above instructions in a message box, HyperCard quickly informs you of the error of your ways. But if you use a go card command in a script and the card doesn’t exist, HyperCard gives you no visible information to that effect. To prove this (you are keeping your skeptic antenna on at all times, aren’t you?), open a stack with fewer than 100 cards and create a button with this script:

on mouseUp
go to card 100
end mouseUp

Now press the button. See what I mean? The visible card doesn’t change, but neither does HyperCard issue an error message. The first time I encountered this behavior, I figured I’d done something wrong (I was using a computed destination, so the error wasn’t obvious), and I modified the script so that it would play a sound effect after going to the card:

on mouseUp
go to card 100
play “boing”
end mouseUp

Much to my surprise, no card change took place but the sound effect played. (I was hoping that inserting a command that shouldn’t execute if the previous instruction didn’t work would be a good debugging trick. I was completely wrong, and I have talked to dozens of other HyperTalk programmers who’ve had the same idea…with the same result.)

The only way to deal with this problem in HyperTalk is to check the result of such a maneuver explicitly. HyperCard provides a function that will return any error generated by a go or find command failing to execute. This function is called the result. If the command executes normally, this function returns a value of empty; otherwise, it has a value you can test. The most common approach to use is:

on mouseUp
go to card 100
if the result is not empty then
play “boing”
answer “Can’t find that card!”
end if
end mouseUp

You should know a couple things about this function. First, its value is affected only by a find or go command. A return statement in a function can also alter its contents, which are reset to empty by the execution of another command and at the end of a handler —according, at least, to Apple’s official HyperCard Script Language Guide.  An external command or function can also have an effect on its contents.

The most important of these observations is the one that says its value is reset by the execution of another command. Any command will seem to have this effect, so you must check the result immediately after the possibly offending line is executed. Alter the above handler this way, for example:

on mouseUp
go to card 100
put “Hello”
if the result is not empty then
play “boing”
answer “Can’t find that card!”
end if
end mouseUp

defeats its purpose. The Message box gets the greeting and the if construct is never executed.

Interestingly enough, if you give HyperCard a non-existent stack as a destination for a go command and then test the result after canceling out of the subsequent dialog box, you’ll find the function returns the value “No such card.” Skeptic hat still on? Good! Try this handler and you’ll see what I mean:

on mouseUp
go to stack “nowhere”
put the result
end mouseUp

Unless you have a stack called “nowhere,” or you point HyperCard to some other stack when it asks you to locate that stack, the message box will say, “No such card.” That should probably have been “No such stack” or, perhaps, no error message at all, since HyperCard asks the user for help in locating the stack if it can’t find it on its own.

Of Expressions and Factors ∆ 

Some of this behavior — particularly where it concerns the use of calculations and their enclosure in parentheses — can be cleared up by some comments made by Scott Kamins on Compu-

Serve in a related thread. (Kamins is co-authoring a book on HyperTalk with the language’s designer and developer, Dan Winkler.) There, the offending line was:

if bg fld “Author” of cd j is showAuthor then go cd j

The line failed to work as expected. Following some general advice offered by other forum members, including Dean Wette, the author of this line tried surrounding part of it with parentheses to read as follows:

if (bg fld “Author” of cd j) is showAuthor then go cd j

To his reported surprise, this worked. Kamins had earlier explained this phenomenon, and Doster provided a summary of Kamins’ earlier observations, including this text:

“When HC sees [the first line above], it sees ‘j is showAuthor’ as an expression. In evaluating that expression, it compares the current value of j with the content of showAuthor and finds they do not match. This results in an evaluation of false. At this point, the script line in the eyes of HC says:

if bg fld “Author” of cd false then go cd j

in which case…HC must now find a card named ‘false.’” 

By surrounding the expression with parentheses, though, the author forces HyperTalk to evaluate cd j as it was intended, and all goes well.

YAHCA ∆ 

These interesting observations — at least they’ve been interesting to me as I’ve tried to fathom some of the intricacies of the language with help from some friends and co-laborers — are but a few interesting anomalies we’ve uncovered in HyperCard and HyperTalk. These have given rise to the acronym YAHCA — Yet Another HyperCard Anomaly. 

About The Author ∆ 

Dan Shafer is a peripatetic HyperTalk afficianado and author on the subject. Dan has written two books on HyperTalk — Understanding HyperTalk, and HyperTalk Programming — along with several others on other microcomputer topics.
Please follow and like us:

About the Author

A.P.P.L.E.

The A.P.P.L.E. Website is run by the Apple Pugetsound Program Library Exchange Users Group and is open to all Apple and Macintosh fans and their friends.