4 ms·
We can certainly quibble about the names given in a standard, but "local" is the term the Forth specification uses, so that's what I'm going with. > All variab
by dwheeler 7y ago
We can certainly quibble about the names given in a standard, but "local" is the term the Forth specification uses, so that's what I'm going with.
> All variables in Forth are local variables.
That's true in some sense (that is, all variables must be in scope to refer to them). However, I think that statement is a little misleading.
Traditional Forth variables often do have scope that extends to the end of your program (and possibly beyond). E.g., if your program says:
VARIABLE FOO
Then that's essentially a global variable in other languages; any function can read/fetch from foo (FOO @) or write/store to FOO (new-value FOO !). Indeed, you can read/write them after your program has completed.
Forth locals do not have this extent; they disappear when the function encompassing them returns. I note that Forth locals are allowed to be stored on the return stack, so that is one way to implement them. Thus, Forth locals are basically like "auto" in other languages like C.
- kragen 7y ago> E.g., if your program says: > VARIABLE FOO > Then that's essentially a global variable in other languages; any function can read/fetch from foo (FOO @) or write/store to FOO (new-value FOO !) This is the point where I disagree. Only functions statically within the scope of FOO --- that is, where FOO is visible when they are defined --- can read or write (or call) FOO, unless you pass them a pointer to it. If you write the following function in GCC, we have a similar situation with the variable m: int (*adder(int n))(int) { static int m; int rv(int p) { return m + p; } m = n; return rv; } m is visible to the inner function rv, because it is within its scope. It retains its value after adder returns, because it is statically allocated and thus has unlimited extent. (Static allocation is the only way to get unlimited extent in C or Forth, since they don't have garbage collection; woe unto those who attempt to use this adder function in almost any real situation!) But this does not mean that m is a global variable. On the contrary, it is a local variable lexically scoped to the body of adder. A similar situation obtains for traditional Forth variables, it's just that the scopes are not block-structured. But neither are they usually the rest of your program. Several of the problems of global variables in other programming languages are absent or less serious with Forth variables. As I mentioned in the other thread, non-preemptive multitasking avoids the problem of another concurrent thread overwriting the variable except at well-defined (if implicit) yield points, and because each thread has its own dictionary, ordinary variables like FOO can be thread-local. The fact that Forth variables must be declared, and a Forth variable's lexical scope is suspended when another variable of the same name is declared, means that you don't have the collision problem you have in C, where if two libraries both define a global variable called "errnum", it causes a link error, or under some circumstances, both libraries use the same variable. (The wordlist system, providing separate namespaces for separate libraries, also helps with this.) Because recursion doesn't happen implicitly in Forth, and you have a stack you can explicitly save values on, statically-allocated variables don't prevent reentrancy in Forth as they do in old versions of FORTRAN, or as they do if you use them in C. So, yes, Forth "locals" are basically like auto variables in other languages like C, in that they are allocated in the same way. But, in C local variables are implicitly auto, and in Forth they aren't; and in C making a variable non-auto is usually a bad idea, and in Forth it isn't.