Reva: Deferred words
User Manual
for Reva Forth

Deferred Words

The whole point of deferred words is to separate the name of the word and what it does, so that you can change it anytime you want. There are many reasons why you would want to do that. So first you create a deferred word with defer:

 defer do-anything

We now have a new word called do-anything but for the moment it doesn't do anything, which is both annoying and ironic at the same time considering its name. The easiest thing to do is to give it the behavior of another existing word. For that purpose you have to know that the behavior of a word in Reva (and any forth implementation) is defined by its execution token, also abbreviated: xt which simply is the address of the code to execute. You can get the xt of a word with '. So if you do this:

 ' reset

This leaves the xt of reset on the stack instead of executing the word. You can execute that xt with the word execute. But what we're going to do is make the word do-anything act like reset:

 ' reset is do-anything

>So the word is consumes the xt on the stack and assign it to the deferred word that follows. Now if you use the word do-anything, it will empty the stack, just like reset. And that is when you might think: "Well I don't need a deferred word to do that. I can just write a simple word.":

 : do-anything reset ;

"And I can change the behavior at any time if I overwrite this new word."

In fact, you're almost right. It would do more or less the same thing except that overwriting a word doesn't remove its previous definition from the dictionary. So if you make that deferred word change a lot, you rewrite and add a new definition even if it's a behavior that word already had before. Which means that deferred words are highly recommended when you when you want to switch between a limited number of definitions. Not only but it's where it makes a lot of sense. In addition, you cannot change the definition of a word at runtime, whereas a deferred word can be changed whenever you like.

Here is a silly example:

You've got a machine that is counting fruit. It doesn't want to know what kind of fruit it is. It doesn't care. So it uses a deferred word:

 defer fruits

Every time one counts a piece of fruit, a button is pressed which does one of these:

 ' apples is fruits


 ' peaches is fruits

Now you don't necessarily want to give the deferred word the behavior of another existing word. Maybe you have a new behavior in mind. And maybe you don't want to give it a name (it's gonna be called differently anyway). So what we want is what is usually called an "anonymous function". This is a function that has no name and is used for passing a callback as an argument, doing object oriented programming, event hooks or what have you. Here is an example of an anonymous function:

 :: dup + ;

This is the classic definition of the word double. It looks a lot like a colon definition except that there is no name and it leaves something on the stack which is (as you probably guessed) the execution token of that function. So now that the xt is on the stack, we can use it in as an argument in another word. Which means you can pass it to is in order to assign it to our deferred word:

 :: dup + ; is do-anything

Here you go. But one last thing. The word :: is good to use in any context where you want to have an anonymous function, but there is another word that let's you define a new deferred word and give it a behavior in one go. This word is logically called defer:. Which means:

 defer: do-anything dup + ;

Is equivalent to:

 defer do-anything
 :: dup + ; is do-anything