DOES> improvement

  • Follow


I don't like DOES> at all, and would prefer that it go away.

I do have a suggestion for making a slight improvement in DOES>
though. Rather than provide the pfa of the CREATE word on the
parameter stack, provide it on the return stack.

One of the problems with CREATE DOES> is that the user, when writing
the run-time code after DOES> will generally look at the compile-time
code after CREATE and mentally calculate offsets to the data comma'd
in, and use these offsets as magic numbers added onto the base-
address. This results in very error-prone and hard-to-read code. A
better solution is to define a data structure using FIELD. In the
compile-time code, the user would ALLOT this much data and then use
the FIELD-defined words to store the data in there. Similarly, in the
run-time code, the user would use the FIELD-defined words to access
this data. When doing this however, it is most convenient to have the
base-adr on the return stack so that R@ can be used in conjunction
with the FIELD-defined words to access the data. This saves a lot of
stack manipulation. Because of this, the first thing most programmers
(me, anyway) does in the code after the DOES> is a >R to put the base-
address on the return stack. It would be simpler and more efficient to
have DOES> internally put the base-adr there.

In regard to Mark Willis' CREATE DOES> implementation, this isn't
going to be any more efficient than putting the base-adr on the return
stack. With a subroutine-threaded implementation however, the base-adr
is *already* on the return stack because it is put there by a CALL in
the CREATE word as a return-address, although this is actually a data
address. This CALL goes to a short function that pops the "return-
address" (actually the pfa) off the return stack, pushes it onto the
parameter stack, and then jumps into the run-time code after the
DOES>. As I said before, this is grossly inefficient. I provided
SwiftForth disassembly in NOVICE.TXT (www.forth.org\novice.html) to
demonstrate this. My method described above would improve the speed
somewhat however, as there will be no need for DOES> to move the
pointer from the return address to the parameter address and then for
the user to move it back again.

I would recommend that Mark Willis implement DOES> like this, even
though it doesn't improve his ITC efficiency any. Sooner or later, he
is going to want to upgrade his ITC compiler to subroutine-threading,
at which time this method will improve the efficiency. By disregarding
the standard and designing his compiler in a way that makes sense, he
can both promote readability and improve speed.
0
Reply hughaguilar96 (1076) 1/23/2010 12:34:17 AM

Hugh Aguilar wrote:

> I don't like DOES> at all, and would prefer that it go away.
> 
> I do have a suggestion for making a slight improvement in DOES> though.
> Rather than provide the pfa of the CREATE word on the parameter stack,
> provide it on the return stack.

I kind of like that. A big part of the time, the >BODY word is in the 
way. If it was on the return stack it wouldn't be in the way, and you 
could get it with R> or R@ any time you want it.

It might be more efficient that way. Would it be faster on average? R> is 
faster than SWAP etc on some systems, but I expect the speed would vary a 
lot. Systems that defined VARIABLE and CONSTANT with DOES> would have 
slower variables and constants. I doubt there are any general conclusions 
about speed.

It would be simpler sometimes and more complicated other times. Arrays 
would be simpler and offsets would be a bit easier to factor.

: OFFSET ( offset base -- addr ) SWAP CELLS + ;

 .... DOES> OFFSET ....

versus

.... DOES' CELLS R> + ....

Would it be simpler more than half the time? I don't know.

However, I've never heard of any improvement to DOES> that has caught on, 
since the chance from <BUILDS DOES> to CREATE DOES> . People seem to be 
pretty set in their ways about this and they just don't want to change. 
To get them to switch you'd need an improvement that was so obviously 
better that they couldn't help notice the value no matter how hard they 
tried not to see it. This isn't that good.

You can do it your own way but nobody will copy you, and it will make 
your code hard for other people to read.
0
Reply J 1/23/2010 1:03:38 AM


Op Sat, 23 Jan 2010 01:03:38 GMT schreef J Thomas:

> Hugh Aguilar wrote:
> 
>> I don't like DOES> at all, and would prefer that it go away.
>> 
>> I do have a suggestion for making a slight improvement in DOES> though.
>> Rather than provide the pfa of the CREATE word on the parameter stack,
>> provide it on the return stack.
> 
> I kind of like that. A big part of the time, the >BODY word is in the 
> way. If it was on the return stack it wouldn't be in the way, and you 
> could get it with R> or R@ any time you want it.
> 
> It might be more efficient that way. Would it be faster on average? R> is 
> faster than SWAP etc on some systems, but I expect the speed would vary a 
> lot. Systems that defined VARIABLE and CONSTANT with DOES> would have 
> slower variables and constants. I doubt there are any general conclusions 
> about speed.
> 
> It would be simpler sometimes and more complicated other times. Arrays 
> would be simpler and offsets would be a bit easier to factor.
> 
>: OFFSET ( offset base -- addr ) SWAP CELLS + ;
> 
>  .... DOES> OFFSET ....
> 
> versus
> 
> ... DOES' CELLS R> + ....
> 
> Would it be simpler more than half the time? I don't know.
> 
> However, I've never heard of any improvement to DOES> that has caught on, 
> since the chance from <BUILDS DOES> to CREATE DOES> . People seem to be 
> pretty set in their ways about this and they just don't want to change. 
> To get them to switch you'd need an improvement that was so obviously 
> better that they couldn't help notice the value no matter how hard they 
> tried not to see it. This isn't that good.
> 
> You can do it your own way but nobody will copy you, and it will make 
> your code hard for other people to read.

One of my Forths uses this. With e.g. multidimensional arrays you can
do all sorts of index calculation before you add the base address that
is easy accessible with R@ or R>.
I haven't found a nice name for DOES>-without->R yet.

-- 
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html
0
Reply Coos 1/23/2010 12:06:34 PM

Coos Haak wrote:
> schreef J Thomas:
>> Hugh Aguilar wrote:
>> 
>>> I do have a suggestion for making a slight improvement in DOES>
>>> though. Rather than provide the pfa of the CREATE word on the
>>> parameter stack, provide it on the return stack.
>> 
>> I kind of like that. A big part of the time, the >BODY word is in the
>> way. If it was on the return stack it wouldn't be in the way, and you
>> could get it with R> or R@ any time you want it.

> One of my Forths uses this. With e.g. multidimensional arrays you can do
> all sorts of index calculation before you add the base address that is
> easy accessible with R@ or R>.
> I haven't found a nice name for DOES>-without->R yet.

OK, I propose that we take all the improvements on DOES> we can find and 
put them all together into a new word that can be defined in high-level 
Forth. The high-level version doesn't have to be efficient, but it makes 
it portable and gives everybody an easy way to try it out. Then if enough 
people like it, we can get efficient versions for various individual 
Forths.

Here's one possible way to do the minimum:

-------------------

: MAKE-ACTION ( addr -*in)
   DUP CELL+ SWAP @  EXECUTE ;

: MAKES ( xt -- )
   CREATE , DOES> MAKE-ACTION ;

: WILL-DO: ( -- colon-sys )
   :NONAME POSTPONE >R ;

: :L ( x -- colon-sys )
   >R : R> POSTPONE LITERAL ;

: MAKER: ( xt -- )
   :L POSTPONE MAKES ;

------------------

Here are a couple of examples with minimal testing:

WILL-DO: ( i1 i2 )
   R@ @ * + 1+ CELLS R> + ;

DUP

\ simple maker
MAKER: 2array1  ;

\ maker that allots data
MAKER: 2array2 5 , ;

\ 2-line 2D array that assigns 5 items/line
2array1 test1 5 ,
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,

\ 2-line 2D array that must have 5 items/line
2array2 test2
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,

: testing ( xt -- )
   2 0 DO
   5 0 DO
     DUP i j ROT EXECUTE @  .
   LOOP
   LOOP DROP ;

cr ' test1 testing
cr ' test2 testing
\ both should print  1 2 3 4 5 6 7 8 9 10

\ array with 6 items/line
2array1 test3 6 ,
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,

\ change array from 5 to 6 items/line
6 ' test2 >BODY CELL+ !

cr ' test3 testing
cr ' test2 testing
\ both should print 1 2 3 4 5 7 8 9 10 11
----------------------

This was designed to be easy in high-level code and easy to port. The 
syntax is:

WILL-DO: code that child will execute ;
\ address of start of data is on return stack when this code executes

MAKER: maker-name  optional-data-allotting ;
\ whatever code you put after maker-name will execute when every child is 
\ created.

And later you do:

maker-name child-name more-data-allotting

' child-name >BODY gives the address of the code that the child executes.
' child-name >BODY CELL+ gives the address of the start of data.

The address of the DOES> code is available to Forth. You can change it to 
something else if you want to, if you have SEE you can look at it, 

: >DATA ( xt -- addr )
   >BODY CELL+ ;

I see no particular disadvantage to having the code available at >BODY 
unless on some systems it's harder to get machine code to use that 
address.

Since you provide MAKER: with an xt, you can give it any existing xt if 
you want to. If you use WILL-DO: then the >DATA address will be on the 
return stack, otherwise it won't. It might be better to always use that 
on the assumption that more efficient implementations might put it on the 
return stack at some other step.

We lose the DOES> ability to affect an already-created CREATE word. This 
is not a big deal, since DOES> can only affect the last word CREATED and 
there is usually no big advantage to do CREATE and allot some of the data 
and then do DOES> . You will almost always know you are going to do DOES> 
when you do CREATE and there would be little to lose by doing the DOES> 
part before you allot any data, except the syntax of DOES> doesn't make 
that easy.
0
Reply J 1/23/2010 5:05:08 PM

J Thomas wrote:
> Hugh Aguilar wrote:
> 
>> I don't like DOES> at all, and would prefer that it go away.
>>
>> I do have a suggestion for making a slight improvement in DOES> though.
>> Rather than provide the pfa of the CREATE word on the parameter stack,
>> provide it on the return stack.
> 
....
> 
> Would it be simpler more than half the time? I don't know.

No, based on many years of making many such definitions.  And systems 
generating code will do a great job of either; you can't measure a 
difference.

> However, I've never heard of any improvement to DOES> that has caught on, 
> since the chance from <BUILDS DOES> to CREATE DOES> . People seem to be 
> pretty set in their ways about this and they just don't want to change. 
> To get them to switch you'd need an improvement that was so obviously 
> better that they couldn't help notice the value no matter how hard they 
> tried not to see it. This isn't that good.

That's not stodginess, it's appropriate behavior if you're supporting 
thousands of users with many thousands of lines of code.  You need a 
really significant change to justify being that disruptive.

> You can do it your own way but nobody will copy you, and it will make 
> your code hard for other people to read.

And there are many who do just that, unfortunately.  Look at how much 
time we spend trying to straighten out unfortunate users of JonesForth.

Cheers,
Elizabeth

-- 
==================================================
Elizabeth D. Rather   (US & Canada)   800-55-FORTH
FORTH Inc.                         +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================
0
Reply Elizabeth 1/23/2010 5:42:36 PM

In article <KVr6n.3360$3n2.1818@newsfe01.iad>,
J Thomas  <jethomas5@gmail.com> wrote:
>Hugh Aguilar wrote:
>
>> I don't like DOES> at all, and would prefer that it go away.
>>
>> I do have a suggestion for making a slight improvement in DOES> though.
>> Rather than provide the pfa of the CREATE word on the parameter stack,
>> provide it on the return stack.
>
>I kind of like that. A big part of the time, the >BODY word is in the
>way. If it was on the return stack it wouldn't be in the way, and you
>could get it with R> or R@ any time you want it.
>
>It might be more efficient that way. Would it be faster on average? R> is
>faster than SWAP etc on some systems, but I expect the speed would vary a
>lot. Systems that defined VARIABLE and CONSTANT with DOES> would have
>slower variables and constants. I doubt there are any general conclusions
>about speed.
>
>It would be simpler sometimes and more complicated other times. Arrays
>would be simpler and offsets would be a bit easier to factor.
>
>: OFFSET ( offset base -- addr ) SWAP CELLS + ;
>
> .... DOES> OFFSET ....
>
>versus
>
>... DOES' CELLS R> + ....
>
>Would it be simpler more than half the time? I don't know.
>
>However, I've never heard of any improvement to DOES> that has caught on,
>since the chance from <BUILDS DOES> to CREATE DOES> . People seem to be
>pretty set in their ways about this and they just don't want to change.
>To get them to switch you'd need an improvement that was so obviously
>better that they couldn't help notice the value no matter how hard they
>tried not to see it. This isn't that good.

My class is a generalisation of DOES> with multiple DOES> fields
injected at the place of the correct offset:
_ _ _  class VEC3
M: X @ M;   M: X! SWAP ! M;  ,
M: Y @ M;   M: Y! SWAP ! M;  ,
M: Z @ M;   M: Z! SWAP ! M;  ,
endclass

This is all based on using CREATE DOES> that is perfectly
sound IMO as a building block. Note that the offsets that
are in the way, and base of the proposal, are not even visible
here.

        5 4 3 VEC3 ape
creates a vector with 3 components.

Z find the offset of the third element.
On the stack off course, just fetch it.
The pointer you want to have on the return stack is hidden
in the current VEC3 pointer ( ^VEC3 ).

Your proposal is very bad for factoring and building new
definitions using the fields.

I can proceed from here and define *outside* and *separate* from
my class:
        : |V|  X DUP *   Y DUP *   Z DUP *  + + ;
        ape |V| .
        50 OK
In your case it would look
: |V|
      ape X R> DUP *
      ape Y R> DUP *
      ape Z R> DUP *
      + +
;
Absolutely horrendous even without the requirement that |V|
should work on any vector.

Interesting is also an unbalanced use of X (bound to happen).
Crash!

>
>You can do it your own way but nobody will copy you, and it will make
>your code hard for other people to read.


Groetjes Albert


--
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

0
Reply Albert 1/24/2010 11:56:07 AM

Albert van der Horst wrote:
> J Thomas <jethomas5@gmail.com> wrote:
>>Hugh Aguilar wrote:
>>
>>> I don't like DOES> at all, and would prefer that it go away.
>>>
>>> I do have a suggestion for making a slight improvement in DOES>
>>> though. Rather than provide the pfa of the CREATE word on the
>>> parameter stack, provide it on the return stack.
>>
>>I kind of like that. A big part of the time, the >BODY word is in the
>>way. If it was on the return stack it wouldn't be in the way, and you
>>could get it with R> or R@ any time you want it.

> My class is a generalisation of DOES> with multiple DOES> fields
> injected at the place of the correct offset: _ _ _  class VEC3
> M: X @ M;   M: X! SWAP ! M;  ,
> M: Y @ M;   M: Y! SWAP ! M;  ,
> M: Z @ M;   M: Z! SWAP ! M;  ,
> endclass

I've done something like that. It wasn't at all hard to do, but I got all 
enthusiastic about parsing and had it automatically make X! when you give 
it X etc and it wound up too baroque.
 
> This is all based on using CREATE DOES> that is perfectly sound IMO as a
> building block. Note that the offsets that are in the way, and base of
> the proposal, are not even visible here.

Sure.

> Your proposal is very bad for factoring and building new definitions
> using the fields.

I thought about that. With a non-optimising compiler this approach often 
results in simpler code, but if you factor out words that use the special 
address then you have to provide it to them. And in that case it starts 
to add complication instead of remove it. I don't have any firm 
conclusion yet.

> I can proceed from here and define *outside* and *separate* from my
> class:
>         : |V|  X DUP *   Y DUP *   Z DUP *  + + ; ape |V| .
>         50 OK
> In your case it would look
> : |V|
>       ape X R> DUP *
>       ape Y R> DUP *
>       ape Z R> DUP *
>       + +
> ;
> Absolutely horrendous even without the requirement that |V| should work
> on any vector.

You're keeping three different items on the return stack, which is likely 
to be trouble regardless. Even if you use R@ 2R@ R'@ that only give you 
access to the top two, and I'm unclear about how you'd do this at all 
with my code. This looks like a terrible way to extend what I was doing, 
but maybe there's no good way to extend it to do what you want to do.

> Interesting is also an unbalanced use of X (bound to happen). Crash!

Good point. I haven't had that yet, but it will surely happen if I keep 
using it. It might help to have the word itself automatically do RDROP so 
I'd always use R@ and never R> . I'd have to be careful never to use EXIT 
without first using RDROP . I think that would result in fewer errors but 
they'd be just as serious. 
 
There's a good chance that when I get tired of playing with this, I'll 
keep it in reserve in case I find uses where it justifies the bother. 
Multiple people have looked at it before, and sound like they haven't 
completely rejected it. With a portable version in high-level Forth 
anybody can look at it and see if they like what it does, or modify it to 
suit themselves.
0
Reply J 1/24/2010 6:22:54 PM

J Thomas wrote:
> Hugh Aguilar wrote:
>
> > I don't like DOES> at all, and would prefer that it go away.
> >
> > I do have a suggestion for making a slight improvement in DOES> though.
> > Rather than provide the pfa of the CREATE word on the parameter stack,
> > provide it on the return stack.
>
> I kind of like that. A big part of the time, the >BODY word is in the
> way. If it was on the return stack it wouldn't be in the way, and you
> could get it with R> or R@ any time you want it.

And just as easily you can use  >R  ... R@  ... R>  .

Then you won't have to do this:

    ... DOES>  R>  @
    ... DOES>  R>  @+  ...  @+  ...  @+
    ... DOES>  R>  ...  MOVE

Attempting to optimize for one particular application typically
comes at the expense of others.  General-purpose functions
need to be effective in a variety of situations, not just one.

--
BTW if one accepts the pfa would be better on the return stack
(which I don't), then the word to change is  CREATE .  For it is
CREATE 's  run-time that pushes the pfa onto the data stack
- not DOES> .  DOES>  merely postpones it.


0
Reply Ed 1/26/2010 4:39:35 AM

On Jan 25, 8:39=A0pm, "Ed" <nos...@invalid.com> wrote:
> Attempting to optimize for one particular application typically
> comes at the expense of others. =A0General-purpose functions
> need to be effective in a variety of situations, not just one.

It is pretty much *always* going to improve readability to define a
record and then use the FIELD-defined words to access the record both
while building it at compile-time (the code after CREATE), and while
accessing it at run-time (the code after DOES>). This isn't a
"particular application," this is a style of programming used for
enhancing readability.

The only exception would be very tiny records that have only one datum
in them. An example would be DEFER. In this case, defining a record
would be an overkill. Having the pfa on the return-stack doesn't cause
any significant complication though, so no harm is done.

: xxx ( --- )
    true abort" *** a DEFER word was never initialized ***" ;

: defer ( -- )       \ my way
    create  ['] xxx ,
    does> r> @ execute ;

: defer ( -- )       \ the ANS-Forth way
    create  ['] xxx ,
    does>  @ execute ;

: [is] ( xt -- )     \ stream: defer-word
    state @ 0=3D abort" *** [IS] only works inside of colon definitions
***"
    postpone [']
    postpone >body
    postpone ! ;
immediate

: is ( xt -- )       \ stream: defer-word
    state @ abort" *** IS only works while interpretting ***"
    '  >body ! ;
0
Reply Hugh 1/26/2010 8:55:14 PM

Op Tue, 26 Jan 2010 12:55:14 -0800 (PST) schreef Hugh Aguilar:

> On Jan 25, 8:39�pm, "Ed" <nos...@invalid.com> wrote:
>> Attempting to optimize for one particular application typically
>> comes at the expense of others. �General-purpose functions
>> need to be effective in a variety of situations, not just one.
> 
> It is pretty much *always* going to improve readability to define a
> record and then use the FIELD-defined words to access the record both
> while building it at compile-time (the code after CREATE), and while
> accessing it at run-time (the code after DOES>). This isn't a
> "particular application," this is a style of programming used for
> enhancing readability.
> 
> The only exception would be very tiny records that have only one datum
> in them. An example would be DEFER. In this case, defining a record
> would be an overkill. Having the pfa on the return-stack doesn't cause
> any significant complication though, so no harm is done.
> 
>: xxx ( --- )
>     true abort" *** a DEFER word was never initialized ***" ;
> 
>: defer ( -- )       \ my way
>     create  ['] xxx ,
>     does> r> @ execute ;
Can't you rename this DOES> ? Some expect a fairly standard behaviour
for words that have standard names.

> 
>: defer ( -- )       \ the ANS-Forth way
>     create  ['] xxx ,
>     does>  @ execute ;
> 
>: [is] ( xt -- )     \ stream: defer-word
>     state @ 0= abort" *** [IS] only works inside of colon definitions
> ***"
>     postpone [']
>     postpone >body
>     postpone ! ;
> immediate

Better write this as:
: [is]
    state @ 0= abort" *** [IS] only works inside of colon definitions
***"
    ' >body postpone literal postpone !
; immediate

> 
>: is ( xt -- )       \ stream: defer-word
>     state @ abort" *** IS only works while interpretting ***"
>     '  >body ! ;
Make that IMMEDIATE otherwise it's not catched in a definition ;-)

-- 
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html
0
Reply Coos 1/27/2010 1:23:13 AM

On Jan 26, 5:23=A0pm, Coos Haak <chfo...@hccnet.nl> wrote:
> >: [is] ( xt -- ) =A0 =A0 \ stream: defer-word
> > =A0 =A0 state @ 0=3D abort" *** [IS] only works inside of colon definit=
ions
> > ***"
> > =A0 =A0 postpone [']
> > =A0 =A0 postpone >body
> > =A0 =A0 postpone ! ;
> > immediate
>
> Better write this as:
> : [is]
> =A0 =A0 state @ 0=3D abort" *** [IS] only works inside of colon definitio=
ns
> ***"
> =A0 =A0 ' >body postpone literal postpone !
> ; immediate

I don't know of any reason why I "better" write this your way. Mine
works perfectly well. The only advantage of yours is that it does the
>BODY at compile-time rather than run-time. This might be slightly
faster on a non-optimizing compiler, but the difference is pretty
minor.

> >: is ( xt -- ) =A0 =A0 =A0 \ stream: defer-word
> > =A0 =A0 state @ abort" *** IS only works while interpretting ***"
> > =A0 =A0 ' =A0>body ! ;
>
> Make that IMMEDIATE otherwise it's not catched in a definition ;-)

It is immediate.
0
Reply Hugh 1/27/2010 9:56:15 PM

Hugh Aguilar wrote:
> On Jan 25, 8:39 pm, "Ed" <nos...@invalid.com> wrote:
> > Attempting to optimize for one particular application typically
> > comes at the expense of others. General-purpose functions
> > need to be effective in a variety of situations, not just one.
>
> It is pretty much *always* going to improve readability to define a
> record and then use the FIELD-defined words to access the record both
> while building it at compile-time (the code after CREATE), and while
> accessing it at run-time (the code after DOES>). This isn't a
> "particular application," this is a style of programming used for
> enhancing readability.
>
> The only exception would be very tiny records that have only one datum
> in them. An example would be DEFER. In this case, defining a record
> would be an overkill. Having the pfa on the return-stack doesn't cause
> any significant complication though, so no harm is done.
> ...

Readibility construes from following the rules and not making
arbitrary exceptions.

Forth uses the data stack for parameter passing and operations.
The return stack is used only for temporary storage e.g. when
the data stack is too busy.

I would see it as both inconsistent and confusing to have data
referenced by a  CREATE 'd word behave differently from
data within a  CREATE ... DOES> .




0
Reply Ed 1/27/2010 11:02:36 PM

Op Wed, 27 Jan 2010 13:56:15 -0800 (PST) schreef Hugh Aguilar:

> On Jan 26, 5:23�pm, Coos Haak <chfo...@hccnet.nl> wrote:
>>>: [is] ( xt -- ) � � \ stream: defer-word
>>> � � state @ 0= abort" *** [IS] only works inside of colon definitions
>>> ***"
>>> � � postpone [']
>>> � � postpone >body
>>> � � postpone ! ;
>>> immediate
>>
>> Better write this as:
>>: [is]
>> � � state @ 0= abort" *** [IS] only works inside of colon definitions
>> ***"
>> � � ' >body postpone literal postpone !
>> ; immediate
> 
> I don't know of any reason why I "better" write this your way. Mine
> works perfectly well. The only advantage of yours is that it does the
>>BODY at compile-time rather than run-time. This might be slightly
> faster on a non-optimizing compiler, but the difference is pretty
> minor.

My definition compiles only the address and the ! and would result in
smaller code.
' is for looking up in run-time, it leaves xt on the stack.
['] is for looking up at compile-time, it compiles xt as a number.
In Gforth this would be no minor difference.
You have to be sure when postpone'ing immediate words.
Like S" in the other thread.

> 
>>>: is ( xt -- ) � � � \ stream: defer-word
>>> � � state @ abort" *** IS only works while interpretting ***"
>>> � � ' �>body ! ;
>>
>> Make that IMMEDIATE otherwise it's not catched in a definition ;-)
> 
> It is immediate.

I believe you, I just didn't see the word immediate.
-- 
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html
0
Reply Coos 1/28/2010 12:09:58 AM

On Jan 27, 3:02=A0pm, "Ed" <nos...@invalid.com> wrote:
> Readibility construes from following the rules and not making
> arbitrary exceptions.
>
> Forth uses the data stack for parameter passing and operations.
> The return stack is used only for temporary storage e.g. when
> the data stack is too busy.

DOES> is already an exceptional word, unlike anything else in Forth.
People will put a stack-picture comment after DOES> to indicate what
parameters the defined word expects on the stack, and what parameters
it will be leaving. The confusing part, is that the DOES> code also
expects to have the pfa of the CREATE word on the stack. The user
didn't put it there though --- it just magically appeared on the
stack. This makes the stack-picture comment confusing because if you
put the pfa in the stack-picture, the user might think that he is
supposed to put the pfa on the stack, which he isn't. If you don't put
the pfa in the stack-picture, a person reading the code could forget
that the pfa is assumed to be there and will be confused by the code.
All in all, DOES> is very confusing for novice Forth programmers. It
seems to me that, if the pfa is going to magically appear, it might
was well appear on the return stack rather than the parameter stack.

All in all, DOES> is just a weird aspect of Forth that is going to be
confusing no matter where the pfa appears. That is why I use :NAME 99%
of the time!
0
Reply Hugh 1/28/2010 9:29:34 PM

Hugh Aguilar wrote:
> On Jan 27, 3:02 pm, "Ed" <nos...@invalid.com> wrote:
> > Readibility

aka "readability"

> > construes from following the rules and not making
> > arbitrary exceptions.
> >
> > Forth uses the data stack for parameter passing and operations.
> > The return stack is used only for temporary storage e.g. when
> > the data stack is too busy.
>
> DOES> is already an exceptional word, unlike anything else in Forth.
> People will put a stack-picture comment after DOES> to indicate what
> parameters the defined word expects on the stack, and what parameters
> it will be leaving. The confusing part, is that the DOES> code also
> expects to have the pfa of the CREATE word on the stack. The user
> didn't put it there though --- it just magically appeared on the
> stack. This makes the stack-picture comment confusing because if you
> put the pfa in the stack-picture, the user might think that he is
> supposed to put the pfa on the stack, which he isn't. If you don't put
> the pfa in the stack-picture, a person reading the code could forget
> that the pfa is assumed to be there and will be confused by the code.
> All in all, DOES> is very confusing for novice Forth programmers. It
> seems to me that, if the pfa is going to magically appear, it might
> was well appear on the return stack rather than the parameter stack.
>
> All in all, DOES> is just a weird aspect of Forth that is going to be
> confusing no matter where the pfa appears. That is why I use :NAME 99%
> of the time!

The convention is to show the child's stack effects.  So:

    : ARRAY
      CREATE  ( #cells  "name" )  CELLS ALLOT
      DOES>  ( i -- 'cell )  SWAP CELLS + ;

The stack comments inform  a) how to define a child and
b) the child's run-time effect.

That's sufficient because a reader is typically interested
in how to use the child - not its internal workings.

If he wants to know the internal workings, he has only to
look at the code following  DOES>  taking into account
the  pfa  automatically generated when a child is invoked.

Given a decent tutorial and examples, there's nothing
complex about  CREATE ... DOES>  that a novice
shouldn't be able to understand.


0
Reply Ed 1/30/2010 9:44:48 AM

14 Replies
75 Views

(page loaded in 0.72 seconds)

Similiar Articles:


















7/16/2012 11:00:34 AM


Reply: