Forth modularity
Contents
Sources
Leo Brodie, Thinking Forth: A Language and Philosophy for Solving Problems, 2004 Edition, Chapter 1: The Philosophy of Forth
Significance
Modularity is “Forth’s most significant breakthrough” in that
the smallest atom of a Forth program is not a module or a subroutine or a procedure, but a “word.” Furthermore, there are no subroutines, main programs, utilities, or executives, each of which must be invoked differently. Everything in Forth is a word. (Brodie, Thinking Forth 19)
Information hiding
Suppose that we have defined a variable apples
as follows, and used it
extensively in a program.
variable apples
But over time, the application of the program changes, and we find that
instead of a single category apples
, we ought to have started with
two categories: red apples and green apples. Instead of rewriting the
program, Brodie suggests that we redefine apples
to “supply two
different [memory] addresses depending on which kind of apple we’re
currently talking about” (25).
variable color ( pointer to current tally )
variable reds ( tally of red apples )
variable greens ( tally of green apples )
: red ( set apple type to red ) reds color ! ;
: green ( set apple type to green) greens color ! ;
: apples ( -- adr of current apple tally ) color @ ;
apples
is no longer a variable; now it is a colon definition whose
function is to get the contents of the variable color
, which stores
the memory address of either the variable reds
or the variable greens
.
Now we can keep tallies of both red and green apples.
5 red apples !
10 green apples !
Let’s define some test words to verify the current tallies:
: test-red ( n -- ) assert( reds @ = ) ;
: test-green ( n -- ) assert( greens @ = ) ;
5 test-red
10 test-green
This does not change the original usage of apples
in existing code. We
can continue using the word apples
as before. Now, via the contents of
the variable color
, it gets the tally of whatever color apples are
currently set to: that is, whichever of red
or green
was most
recently called. We can continue using it with that reference.
: test-apples ( n -- ) assert( apples @ = ) ;
10 test-apples
1 apples +!
11 test-apples
11 test-green
Brodie, Thinking Forth 26:
Look again at what we did. We changed the definition of
APPLES
from that of a variable to a colon definition, without affecting its usage. Forth allows us to hide the details of howAPPLES
is defined from the code that uses it. What appears to be “thing” (a variable) to the original code is actually defined as an “action” (a colon definition) within the component. […] Only Forth, which eliminates theCALL
s from procedures, which allows addresses and data to be implicitly passed via the stack, and which provides direct access to memory locations with@
and!
, can offer this level of information-hiding. Forth pays little attention to whether something is a data structure or an algorithm.
Execute this file
$ codedown forth < modularity.md | grep . | gforth
Gforth 0.7.3, Copyright (C) 1995-2008 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
variable apples ok
variable color ( pointer to current tally ) ok
variable reds ( tally of red apples ) ok
variable greens ( tally of green apples ) ok
: red ( set apple type to red ) reds color ! ; ok
: green ( set apple type to green) greens color ! ; ok
: apples ( -- adr of current apple tally ) color @ ; redefined apples ok
5 red apples ! ok
10 green apples ! ok
: test-red ( n -- ) assert( reds @ = ) ; ok
: test-green ( n -- ) assert( greens @ = ) ; ok
5 test-red ok
10 test-green ok
: test-apples ( n -- ) assert( apples @ = ) ; ok
10 test-apples ok
1 apples +! ok
11 test-apples ok
11 test-green ok