Re: Forth Frustrations
- From: "J Thomas" <jethomas5@xxxxxxxxx>
- Date: 11 Apr 2007 19:47:30 -0700
On Apr 11, 4:37 pm, Albert van der Horst <alb...@xxxxxxxxxxxxxxxxxx>
wrote:
In article <1176269248.701810.283...@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>,
J Thomas <jethom...@xxxxxxxxx> wrote:
It makes logical sense to have a word that doesn't parse. But I can't
see writing
:: DUP * ; S" SQUARE" NAMED!
{ DUP * } "SQUARE" DEFINED
wouldn't be too bad.
But then, why try to reinvent PostScript?
If they do something better, why not copy them? Because we have too
much inertia. Because the Forth community is too stodgy and
conservative.
The extra S" " bother me because I'm used to something different.
Maybe with practice I'll see that it's better that way.
It bothers because it is stupid.
We invent
<body> <name> <couple>
because we don't want <couple> to look ahead in the input stream.
Then we implement it using S" that does look ahead in the input stream!
The PostScript like approach only makes sense if strings
are promoted to first class citizens in the language.
It sounds like you're talking about something deeply philosophical.
I like the idea of words that work with strings instead of parsing
things from the input stream, because it's too hard to manipulate the
input stream. If you just want to get the result you have to find a
way to put the parsing word and the string parsed both into a buffer
together and evaluate the buffer, which is more work than it ought to
be.
But people usually prefer words that use the input stream because
that's what they do the most and it's good for the most-used case to
be easy.
If you have a word that accepts a string then it's easy to get the
string from the input stream and use it, while it's harder to go the
other direction. So it makes a certain sense for the core primitives
to use strings instead of parsing -- except for PARSE and PARSE-NAME .
But it's simply easier to do
.." abc" than " abc" ." -- 3 less characters.
Similarly ' ['] CHAR [CHAR] ABORT" : CONSTANT VARIABLE CREATE VALUE
etc.
We could build in a parsing token into the compiler so it knows to
collect a string and hold it ready to use, and then we could have
words that use the waiting string. We could call the token " say. And
we could do "FOO to tell the compiler to keep FOO ready, and we could
agree not to have any words that begin with " . Or we could use a
space between the token and the word, and then we could have words
that start with " . And the deep important difference between having
the compiler look at " FOO and know it should keep FOO as a string for
another routine to use, versus having " be a word that parses FOO and
keeps it for another routine to use is....
Anyway, I'm tired of arguing this. I don't claim the advantages of
putting the name at the end are big in themselves, and lots of people
prefer the name at the beginning. It isn't like doing most things
postfix, where the advantages are worth having that be the thing that
everybody who uses another language thinks about when they think about
Forth, if they've ever heard of Forth.
About a DOES> alternative.
Putting aside the magic, what a DOES> child does is basicly this:
It puts 2 values on the stack, an address and an execution token. Then
it executes the xt.
The address was HERE after the child was completed.
Give up having DOES: work on a word that's already made by CREATE .
That's a historical accident that has no particular advantage. How can
we implement that child?
One way is to have the xt handy and compute where HERE will be, and
lay down the two literals and then the execute, and then ; . You know
where HERE will be because every child has exactly the same format,
two literals and an execute.
A less-efficient but far more flexible way is like this --
..... ( xt ) HERE >R , 0 ,
: R@ POSTPONE LITERAL POSTPONE 2@ POSTPONE EXECUTE POSTPONE ; HERE R>
CELL+ ! ;
2@ is presumably less efficient than a second literal. But you can
change the address and you can change the xt. Your DOES: word is both
a VALUE and a DEFERed word.
You can get those advantages the first way if you can reach into your
compiled code and change the literals. Standard Forth can't do that,
but implementation-dependent code usually can.
You don't have to use an address. If you only want one value instead
of a whole data structure, you can use the value itself instead of the
address, and your xt can save the step of fetching the value. So for
example many assemblers have CREATE DOES> words that use only one bit-
pattern. Those could get a little smaller and faster. Not a critical
issue.
With a few words, the complexity of DOES> goes away.
One word -- for the moment call it DOES: -- accepts a value and an xt
and creates a child word that puts the pair on the stack and executes
the upper one.
One word changes the xt.
One word changes the value.
One word changes the value to HERE .
The DOES> functionality we lose is the ability to change an existing
CREATEd definition without adding any code or data beyond the end of
that CREATEd definition. There are ways to get that functionality even
with standard code, by having an unused child waiting, but I don't see
that it's worth bothering with.
You could get the effect of DEFER and VALUE easily with DOES> . Just
get the address you want to use and do ( addr ) ' child >BODY ! . And
have the code after DOES> do an extra @ to get the new address.
DEFER FOO
.... DOES> @ FOO ;
But this is a complication that may not come naturally. Why should
DOES> be restricted to the code-after-DOES> affecting the address
provided by the last CREATEd word? Why have complicated code to allow
that combination and only that combination, when it's easier with
fewer limitations?
Because this was the perceived need that was first fulfilled, and we
got a tradition of doing it that way. (I guess the first perceived
need resulted in words created with BUILDS> (or was it <BUILDS ?) that
were intended from the first to be changed by DOES> but that did some
or all of their allocation before the DOES> changed them.)
It would be possible to implement the traditional DOES> with these
simpler words (even using high-level standard code plus two of these
words), though there are various complications. (You have to do some
special tricks to CREATE and >BODY . You have to make ; do a lot of
the work for DOES> . Much simpler to do things "under the hood" and
use knowledge about your particular Forth system than do it with
standard code. But I claim it can be done.)
.
- References:
- Re: Forth Frustrations
- From: rickman
- Re: Forth Frustrations
- From: J Thomas
- Re: Forth Frustrations
- From: Bruce McFarling
- Re: Forth Frustrations
- From: J Thomas
- Re: Forth Frustrations
- From: Albert van der Horst
- Re: Forth Frustrations
- Prev by Date: Re: Forth Frustrations
- Next by Date: Re: Forth Frustrations
- Previous by thread: Re: Forth Frustrations
- Next by thread: Re: Forth Frustrations
- Index(es):
Relevant Pages
|