The usual way to handle forward references in Forth is to use DEFER and IS. The CORE EXT wordset includes some other goodies like ACTION-OF, DEFER!, and DEFER@.
This usage provides a kind of OOPless late binding. Dynamic forward references can be changed by DEFER!. What if all you want is a static forward reference? The overhead is a waste of resources.
I use LATER and RESOLVES:
LATER foo \ compiles a jump instruction with a blank address
: bar foo ... ;
:noname ( foo ) ; RESOLVES foo \ fills in the address
The usual way to handle forward references in Forth is to use DEFER and IS. The CORE EXT wordset includes some other goodies like ACTION-OF, DEFER!, and DEFER@.
This usage provides a kind of OOPless late binding. Dynamic forward references can be changed by DEFER!. What if all you want is a static forward reference? The overhead is a waste of resources.
I use LATER and RESOLVES:
LATER foo \ compiles a jump instruction with a blank address
: bar foo ... ;
:noname ( foo ) ; RESOLVES foo \ fills in the address
So, there are some points I would like to make about DEFER:
1. DEFER is used for two different things. The spirit of Forth is for words to do only one thing. It's overkill for the static case.
4. This is almost surely a matter of taste. I don't like to waste RAM and clock cycles.
There are plenty of those to burn these days. However, there is room for improvement in CORE EXT. Perhaps support can be added for simple static forward references.
Comments?
The usual way to handle forward references in Forth is to use DEFER and
IS. The CORE EXT wordset includes some other goodies like ACTION-OF,
DEFER!, and DEFER@.
This usage provides a kind of OOPless late binding. Dynamic forward >references can be changed by DEFER!. What if all you want is a static
forward reference? The overhead is a waste of resources.
I use LATER and RESOLVES:
LATER foo \ compiles a jump instruction with a blank address
: bar foo ... ;
:noname ( foo ) ; RESOLVES foo \ fills in the address
So, there are some points I would like to make about DEFER:
1. DEFER is used for two different things. The spirit of Forth is for
words to do only one thing. It's overkill for the static case.
2. IS can be "smartened up", or overloaded the way TO is, but the >complexification is anti-Forth even if you can make it work.
3. There could be better words to use than LATER and RESOLVES for static >forward references. I have seen IST used, but we are not all German.
4. This is almost surely a matter of taste. I don't like to waste RAM
and clock cycles. There are plenty of those to burn these days. However, >there is room for improvement in CORE EXT. Perhaps support can be added
for simple static forward references.
Comments?
Brad Eckert <hwfwguy@gmail.com> writes:
The usual way to handle forward references in Forth is to use DEFER and IS. The CORE EXT wordset includes some other goodies like ACTION-OF, DEFER!, and DEFER@.
This usage provides a kind of OOPless late binding. Dynamic forward references can be changed by DEFER!. What if all you want is a static forward reference? The overhead is a waste of resources.
I use LATER and RESOLVES:
LATER foo \ compiles a jump instruction with a blank address
: bar foo ... ;
:noname ( foo ) ; RESOLVES foo \ fills in the address
Gforth (development) has FORWARD:
forward foo
: bar foo ;
: foo ." foo" ;
This does not exist because there was a pressing need for it, but
because we found a cute way to implement it. You can read about the implementation in
<http://www.complang.tuwien.ac.at/forth/forward.txt>.
So, there are some points I would like to make about DEFER:
1. DEFER is used for two different things. The spirit of Forth is for words to do only one thing. It's overkill for the static case.
Another design principle in Forth is to avoid unnecessary complexity.
DEFER ... IS can be used to do what LATER ... RESOLVES do. Are there
really enough (and important enough) cases to justify the extra
complexity of LATER...RESOLVES or FORWARD?
1. DEFER is used for two different things. The spirit of Forth is for words to do only one thing.[..]
On Sunday, August 13, 2023 at 5:43:22 AM UTC+2, Brad Eckert wrote:
[..]
1. DEFER is used for two different things. The spirit of Forth is for words to do only one thing.[..]
Maybe that statement is incomplete? See COUNT ( c@+ ), or 2>R ( DO ), or */MOD ( *, /, mod).
Good words do their best to be as low-level / general as possible. They can, and are, used wildly
out of context in some cases, where somebody renamed them to point out a useful re-purpose.
These two characteristics together make it natural to sequence a few of these primitives
together and give them a descriptive name that works better (for the user) in the context at
hand. The best names are ambiguous to make these sequences work in many contexts
(the same idea as in spoken languages).
It should be "COUNT," not "parse-string-descriptor_256."
On Sunday, August 13, 2023 at 5:43:22 AM UTC+2, Brad Eckert wrote:
The usual way to handle forward references in Forth is to use DEFERand IS. The CORE EXT wordset includes some other goodies like ACTION-OF, >DEFER!, and DEFER@.
forward reference? The overhead is a waste of resources.
This usage provides a kind of OOPless late binding. Dynamic forward >references can be changed by DEFER!. What if all you want is a static
I use LATER and RESOLVES:
LATER foo \ compiles a jump instruction with a blank address
: bar foo ... ;
:noname ( foo ) ; RESOLVES foo \ fills in the address
I agree with your comments.
LMI PC/FORTH had F: and R: for this purpose. I found these commands very easy >to memorize and to use. F: defines a forward reference, and R: resolves it. >Example:
F: MENU
(other definitions)
R: MENU (here comes the actual code) ;
Another design principle in Forth is to avoid unnecessary complexity.
DEFER ... IS can be used to do what LATER ... RESOLVES do. Are there
really enough (and important enough) cases to justify the extra
complexity of LATER...RESOLVES or FORWARD?
In my opinion the main benefit of forwarding/resolving a colon definition (instead of DEFER and IS) is clarity of code. In the first case we have static behavior, in the second case a self-modifying program.
A similar case where we introduced two different words for almost the same task are CONSTANT and VALUE
On Sunday, August 13, 2023 at 11:34:49 AM UTC+2, Anton Ertl wrote:
Another design principle in Forth is to avoid unnecessary complexity.
DEFER ... IS can be used to do what LATER ... RESOLVES do. Are there
really enough (and important enough) cases to justify the extra
complexity of LATER...RESOLVES or FORWARD?
In my opinion the main benefit of forwarding/resolving a colon definition (instead of DEFER and IS) is clarity of code. In the first case we have static behavior, in the second case a self-modifying program.
A similar case where we introduced two different words for almost the same task are CONSTANT and VALUE
CONSTANT is not really needed if we have VALUE at hand because we could store any
constant number using VALUE just as well. But if we use CONSTANT in this case we point out clearly that the stored number is not supposed to be changed anywhere in the program.
On Sunday, August 13, 2023 at 11:34:49=E2=80=AFAM UTC+2, Anton Ertl wrote:...
Are there=20
really enough (and important enough) cases to justify the extra=20
complexity of LATER...RESOLVES or FORWARD?
A similar case where we introduced two different words for almost the same >task are CONSTANT and VALUE
The usual way to handle forward references in Forth is to use DEFER and IS. The CORE EXT wordset includes some other goodies like ACTION-OF, DEFER!, and DEFER@.4tH has got PROTO: <name> for defining it and :PROTO <name> for resolving it. The former creates two jumps.
This usage provides a kind of OOPless late binding. Dynamic forward references can be changed by DEFER!. What if all you want is a static forward reference? The overhead is a waste of resources.
I use LATER and RESOLVES:
LATER foo \ compiles a jump instruction with a blank address
: bar foo ... ;
:noname ( foo ) ; RESOLVES foo \ fills in the address
So, there are some points I would like to make about DEFER:
1. DEFER is used for two different things. The spirit of Forth is for words to do only one thing. It's overkill for the static case.
2. IS can be "smartened up", or overloaded the way TO is, but the complexification is anti-Forth even if you can make it work.
3. There could be better words to use than LATER and RESOLVES for static forward references. I have seen IST used, but we are not all German.
4. This is almost surely a matter of taste. I don't like to waste RAM and clock cycles. There are plenty of those to burn these days. However, there is room for improvement in CORE EXT. Perhaps support can be added for simple static forward references.
Comments?
...
Performance wise the difference with DEFER is negligable. It tend to use DEFER when the program
must or can change its target word. A static forward is done with :PROTO. I try to cut down on my
data consumption ;-)
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 300 |
Nodes: | 16 (2 / 14) |
Uptime: | 36:10:34 |
Calls: | 6,707 |
Files: | 12,239 |
Messages: | 5,353,434 |