Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pop quiz for Forth novices

168 views
Skip to first unread message

Hugh Aguilar

unread,
Jun 13, 2011, 10:25:22 PM6/13/11
to
Here is pop quiz to test the Forth novice's understanding of Forth
philosophy. The following RfD was rejected by the Forth-200x committee
because it demonstrates a complete failure to understand *two*
fundamental principles of Forth-200x. What were these fundamental
principles?

If you figure out the correct answer, you get a virtual A+ from our
professor of Forth, Anton Ertl --- he has the final word on whether
your answer is correct or not --- I'm an F student by Anton Ertl's
standards, so I'm not qualified grade the pop quiz myself (I got an F
grade for writing the RfD, and was kicked off the Forth-200x committee
as a result). If you only figure out one of the two fundamental
principles violated, you get a B grade. If you just say, "Because it
sucks, and you're a donkey!," you get a C grade (you are an average
member of comp.lang.forth). If you decline to answer, then you get a D
grade (still better than my F grade).

The RfD has been edited slightly --- the name has been changed from
SIZE to ALLOCATION, most of the Current Practice section has been
deleted for brevity, and a typo in the Solution section has been
fixed.

Note that ALLOCATION has been implemented in the novice package with
the additional feature of allowing FREE and RESIZE to be able to
distinguish between memory in the dictionary and memory in the heap.
Rather than just abort with an error message when given an address in
the dictionary, they respond in a reasonable way (FREE does nothing,
and RESIZE moves the data to the heap).
http://www.forth.org/novice.html
For authenticity, the original simple version is presented here for
the pop quiz --- you get the same challenge that the Forth-200x
committee got. The simple version and the improved version both
contradict the same two fundamental principles though, so the answer
is the same whether you consider this RfD or the code in the novice
package.


Author
-------

Hugh Aguilar


Problem
---------

The program, given an address returned by ALLOCATE or RESIZE, has no
way of finding out how big that chunk of memory is.


Current Practice
--------

When the programmer calls ALLOCATE or RESIZE, he keeps track of the
size somewhere in his own program.


Solution
--------

The solution is to provide a word ALLOCATION that returns the size of
a heap allocation, given the address of that heap allocation (the
address returned by ALLOCATE or RESIZE).


Proposal
---------

Introduce a new word: ALLOCATION ( adr -- size )

This would be in the optional Memory-Allocation word set (chapter 14).

Ron Aaron

unread,
Jun 14, 2011, 12:16:37 AM6/14/11
to
On Jun 14, 5:25 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:

> The program, given an address returned by ALLOCATE or RESIZE, has no
> way of finding out how big that chunk of memory is.

The problem you are trying to solve is not usually a problem.

As you point out:

> When the programmer calls ALLOCATE or RESIZE, he keeps track of the
> size somewhere in his own program.

That is necessarily true, since the progam *must* know how much memory
to ALLOCATE or to RESIZE the pointer to. Since the program *already*
knows this information, it stores it somewhere so it can properly use
the memory being referenced (e.g., not overwrite the end of it, etc.).

The only case I can think of where the ALLOCATION word would really be
useful is in a debugging situation.

Making the memory-allocation words store extra data about the size of
the allocation is potentially wasteful of memory. For example, in
Reva the "allocate" word maps directly to the OS memory allocation
function, and so it truly has no idea how big a memory chunk is.
Therefore in Reva, at least, I would have to allocate an extra cell of
memory and stash the size there (while the OS memory allocator does of
course already know how big the memory allocated is). Other Forths
which manage memory themselves would not have that issue.

Further, if there is a real need in a particular program to know what
the size of a random allocated memory block is, one might simply wrap
ALLOCATE and FREE and RESIZE:

VARIABLE ORIGINAL-ALLOCATE
' ALLOCATE ORIGINAL-ALLOCATE !
: ALLOCATE ( N -- A )
DUP CELL+ ORIGINAL-ALLOCATE
@ EXECUTE
TUCK ! CELL+
;

: ALLOCATION ( A -- N )
CELL- @ ;

(implementation of FREE and RESIZE is trivial, left to the "novice")

BruceMcF

unread,
Jun 14, 2011, 12:46:13 AM6/14/11
to
On Jun 14, 12:16 am, Ron Aaron <rambam...@gmail.com> wrote:
> Further, if there is a real need in a particular program to know what
> the size of a random allocated memory block is, one might simply wrap
> ALLOCATE and FREE and RESIZE:
>
> VARIABLE ORIGINAL-ALLOCATE
> ' ALLOCATE  ORIGINAL-ALLOCATE !
> : ALLOCATE ( N -- A )
>         DUP CELL+ ORIGINAL-ALLOCATE
>         @ EXECUTE
>         TUCK ! CELL+
>         ;

This seems a long-winded way to:

: ALLOCATE ( n -- a ) DUP CELL+ ALLOCATE TUCK ! CELL+ ;

Rod Pemberton

unread,
Jun 14, 2011, 1:43:34 AM6/14/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:371d3747-5420-4260...@g28g2000yqa.googlegroups.com...

>
> Here is pop quiz to test
> [quiz info]
> [...]

Ok.

> The program, given an address returned by ALLOCATE or RESIZE,
> has no way of finding out how big that chunk of memory is.
>

Why is that a problem? Can we call this need or want problem #1?

FYI, you cannot get the size of the memory allocation from a pointer in C
either. It's memory allocator keeps track of that. ISTM that ANS Forth
uses similarly constructed memory operations: ALLOCATE FREE RESIZE . Those
would be like malloc(), free(), realloc(). Forth also has ALLOT which is
probably closer to the non-standard alloca(). Using alloca() is usually
considered poor practice in C. There are all sorts of side effects, usually
unnoticed, that can result from it's use. I'd suspect these issues would or
could affect Forth that is compiled for the same reasons.

> When the programmer calls ALLOCATE or RESIZE, he keeps track
> of the size somewhere in his own program.

Can we call not doing this problem #2? Or, is this still #1?

Reiterating,

> Rather than just abort with an error message when given an address in
> the dictionary, they respond in a reasonable way (FREE does nothing,

Can we call this problem #3? ISTM, there is no apparent need for ANS Forth
spec to respond in any reasonable way. It, like C specs, eliminated the
solid foundation of a computation model or underlying virtual machine.
Without that, everything is open to interpretation. If you don't understand
how and why things work or worked the way they did from a historical
perspective, you'll get lost ... I think that was what you were getting at.
Is that what you were getting at? I thought I noticed some sarcasm ...

> Introduce a new word: ALLOCATION ( adr -- size )
>
> This would be in the optional Memory-Allocation word set (chapter 14).

Can we wall this problem #4? If Forth is like C in this regard, then the
functionality is probably there, but hidden behind some old or new words.
E.g., from the poorly worded ANS specs, RESIZE could be understood to be
*only* a *change* in size of the memory allocation. I.e., it would fail if
the allocation was the same size. Hence, if RESIZE was passed the same 'u'
and 'addr' as passed to and returned from ALLOCATE respectively, then RESIZE
would fail and 'ior' could be a 'implemenetation-defined I/O result code'
for *no change*. Now, I'm not suggesting that. That'll probably break
everything around. Programmers who use C's realloc() generally assume an
identically sized reallocation will succeed. I assume that Forth
programmers do too. But, IIRC, my perfectly *valid* interpretation of ALLOT
from the poorly worded ANS spec a while back was questioned also ...


Rod Pemberton


Julian Fondren

unread,
Jun 14, 2011, 2:01:32 AM6/14/11
to
On Jun 13, 9:25 pm, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> Here is pop quiz to test the Forth novice's understanding of Forth
> philosophy. The following RfD was rejected by the Forth-200x committee
> because it demonstrates a complete failure to understand *two*
> fundamental principles of Forth-200x. What were these fundamental
> principles?

This isn't a question about Forth philosophy, but about some
fundamental principles of Forth-200x. Apart from that, there's
discussion on your proposal from over a year ago. Highlights:

http://tech.groups.yahoo.com/group/forth200x/message/471
http://tech.groups.yahoo.com/group/forth200x/message/462
http://tech.groups.yahoo.com/group/forth200x/message/477
http://tech.groups.yahoo.com/group/forth200x/message/487

It goes without saying that you went off the deep end:

http://tech.groups.yahoo.com/group/forth200x/message/492
http://tech.groups.yahoo.com/group/forth200x/message/497

Your proposal here is identical to your initial proposal, except that
you've dropped your example from Current Practice, except that you've
changed the name of the word. So you've just ignored all of the
discussion about it, the distinction that was made between ALLOCATION
and ALLOCATED , the discussion of some current practice, of some
implementation strategies.

If this RfD was rejected more recently than a year ago, _not wanting
to just rehash this prior discussion_ could be a motivation.

Julian Fondren

unread,
Jun 14, 2011, 2:02:28 AM6/14/11
to
On Jun 13, 11:46 pm, BruceMcF <agil...@netscape.net> wrote:
> On Jun 14, 12:16 am, Ron Aaron <rambam...@gmail.com> wrote:
>
> > Further, if there is a real need in a particular program to know what
> > the size of a random allocated memory block is, one might simply wrap
> > ALLOCATE and FREE and RESIZE:
>
> > VARIABLE ORIGINAL-ALLOCATE
> > ' ALLOCATE  ORIGINAL-ALLOCATE !
> > : ALLOCATE ( N -- A )
> >         DUP CELL+ ORIGINAL-ALLOCATE
> >         @ EXECUTE
> >         TUCK ! CELL+
> >         ;
>
> This seems a long-winded way to:
>
> : ALLOCATE ( n -- a ) DUP CELL+ ALLOCATE TUCK ! CELL+ ;

ALLOCATE 's stack effect is ( u -- a-addr ior )

Andrew Haley

unread,
Jun 14, 2011, 4:47:13 AM6/14/11
to
Ron Aaron <ramb...@gmail.com> wrote:
> On Jun 14, 5:25 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>
>> The program, given an address returned by ALLOCATE or RESIZE, has no
>> way of finding out how big that chunk of memory is.
>
> The problem you are trying to solve is not usually a problem.
>
> As you point out:
>
>> When the programmer calls ALLOCATE or RESIZE, he keeps track of the
>> size somewhere in his own program.
>
> Further, if there is a real need in a particular program to know what
> the size of a random allocated memory block is, one might simply wrap
> ALLOCATE and FREE and RESIZE:
>
> VARIABLE ORIGINAL-ALLOCATE
> ' ALLOCATE ORIGINAL-ALLOCATE !
> : ALLOCATE ( N -- A )
> DUP CELL+ ORIGINAL-ALLOCATE
> @ EXECUTE
> TUCK ! CELL+
> ;

You don't need all this ORIGINAL-ALLOCATE stuff: just call ALLOCATE.

> : ALLOCATION ( A -- N )
> CELL- @ ;
>
> (implementation of FREE and RESIZE is trivial, left to the "novice")

He already knows. He was told this in May 2010.

Andrew.

Josh Grams

unread,
Jun 14, 2011, 9:04:15 AM6/14/11
to
Andrew Haley wrote: <3v-dnQd42KeMvWrQ...@supernews.com>

> Ron Aaron <ramb...@gmail.com> wrote:
>> On Jun 14, 5:25 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>>
>>> The program, given an address returned by ALLOCATE or RESIZE, has no
>>> way of finding out how big that chunk of memory is.
>>
>> The problem you are trying to solve is not usually a problem.
>>
>> As you point out:
>>
>>> When the programmer calls ALLOCATE or RESIZE, he keeps track of the
>>> size somewhere in his own program.
>>
>> Further, if there is a real need in a particular program to know what
>> the size of a random allocated memory block is, one might simply wrap
>> ALLOCATE and FREE and RESIZE:
>>
>> VARIABLE ORIGINAL-ALLOCATE
>> ' ALLOCATE ORIGINAL-ALLOCATE !
>> : ALLOCATE ( N -- A )
>> DUP CELL+ ORIGINAL-ALLOCATE
>> @ EXECUTE
>> TUCK ! CELL+
>> ;
>
> You don't need all this ORIGINAL-ALLOCATE stuff: just call ALLOCATE.

IIRC Reva makes colon definitions visible immediately.

--Josh

Chris Hinsley

unread,
Jun 14, 2011, 9:11:03 AM6/14/11
to
> The program, given an address returned by ALLOCATE or RESIZE, has no
> way of finding out how big that chunk of memory is.

That's a bit crap. But not a serious problem. I don;'t think you can
legally dig into the allocater in C either ? And it gives the allocator
some leeway in what it does.

> When the programmer calls ALLOCATE or RESIZE, he keeps track of the
> size somewhere in his own program.

Well that's stupid as well !

You should only know that you got as much as you asked for, and use no
more. And need to know nothing else ! IMHO.

Chris

Chris Hinsley

unread,
Jun 14, 2011, 9:14:48 AM6/14/11
to

Hey Anton, do I get an A*, there so easy to get these days ? ;)

Chris

Chris Hinsley

unread,
Jun 14, 2011, 9:24:44 AM6/14/11
to
On 2011-06-14 14:11:03 +0100, Chris Hinsley said:

It's a phylasophical issue (crap my spelling is bad), you either ask
how much you want, and get told you much you got (>= to that or fail),
and you can use up to what you got (effiency argument). Or you just get
back a lump that was quickest for the allocator to give you (again,
effeicency arguement) and you don't go beyond what you asked for.

Chris

Andrew Haley

unread,
Jun 14, 2011, 9:25:25 AM6/14/11
to

I must be missing something. I thought the discussion was about
Forth, and standard Forth at that. :-)

Confused,
Andrew.

Ron Aaron

unread,
Jun 14, 2011, 12:39:16 PM6/14/11
to
On Jun 14, 11:47 am, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:

> Ron Aaron <rambam...@gmail.com> wrote:
> > On Jun 14, 5:25 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>
> >> The program, given an address returned by ALLOCATE or RESIZE, has no
> >> way of finding out how big that chunk of memory is.
>
> > The problem you are trying to solve is not usually a problem.
>
> > As you point out:
>
> >> When the programmer calls ALLOCATE or RESIZE, he keeps track of the
> >> size somewhere in his own program.
>
> > Further, if there is a real need in a particular program to know what
> > the size of a random allocated memory block is, one might simply wrap
> > ALLOCATE and FREE and RESIZE:
>
> > VARIABLE ORIGINAL-ALLOCATE
> > ' ALLOCATE  ORIGINAL-ALLOCATE !
> > : ALLOCATE ( N -- A )
> >        DUP CELL+ ORIGINAL-ALLOCATE
> >        @ EXECUTE
> >        TUCK ! CELL+
> >        ;
>
> You don't need all this ORIGINAL-ALLOCATE stuff: just call ALLOCATE.

Ah, I forgot that ANS doesn't recurse automatically like Reva does.
Right, just ignore the original-allocate stuff :)


> > (implementation of FREE and RESIZE is trivial, left to the "novice")
>
> He already knows.  He was told this in May 2010.

Not a surprise.

Ron Aaron

unread,
Jun 14, 2011, 12:41:11 PM6/14/11
to
On Jun 14, 4:25 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
> Josh Grams <j...@qualdan.com> wrote:

> > IIRC Reva makes colon definitions visible immediately.
>
> I must be missing something.  I thought the discussion was about
> Forth, and standard Forth at that.  :-)

Hey! Maybe Reva's the new standard, yeah did you ever think about
THAT?

Chris Hinsley

unread,
Jun 14, 2011, 12:41:31 PM6/14/11
to

And it's not a clear cut case of allways being able to use up the real
amount allocated ! What if the memory system was tracking that it had a
little bit on the end that it could use to facilatate a later allocate ?

I agree it's not likely, but you can't rule it out !

Chris

Anton Ertl

unread,
Jun 14, 2011, 1:23:40 PM6/14/11
to
Chris Hinsley <chris....@gmail.com> writes:
>And it's not a clear cut case of allways being able to use up the real
>amount allocated ! What if the memory system was tracking that it had a
>little bit on the end that it could use to facilatate a later allocate ?

Well, the system (implementor) has the choice:

1) It reports the total of space up to the next ALLOCATEd space or the
end of the managed area; then it has to treat this total as having
been allocated.

2) It reports as allocated what it would treat as allocated for other
purposes (e.g., for FREE); this size may be a little larger than the
argument to ALLOCATE was, but won't include the adjacent FREEs space.

I think I would use option 2 as an implementor. It does not pay off
to treat all this space as allocated if it is not even clear if the
user wants it. Alternatively have separate words for functionality 2
and functionality 1.

>I agree it's not likely, but you can't rule it out !

It's totally likely that there are occurences where there some free
space after an allocted area.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2010: http://www.euroforth.org/ef10/

Alex McDonald

unread,
Jun 14, 2011, 1:44:38 PM6/14/11
to
On Jun 14, 2:11 pm, Chris Hinsley <chris.hins...@gmail.com> wrote:
> > The program, given an address returned by ALLOCATE or RESIZE, has no
> > way of finding out how big that chunk of memory is.
>
> That's a bit crap. But not a serious problem. I don;'t think you can
> legally dig into the allocater in C either ? And it gives the allocator
> some leeway in what it does.

On some platforms you can make requests for memory between a lower and
upper limit; the system returns an address and the length allocated.
But that's just a convenience, since the equivalent freeing of memory
doesn't normally take a length; it takes only an address on the basis
that there's usually a lot more to check before simply releasing it.
Like whether you're permitted to do so, for instance. And the length
may be a convenient fiction anyhow; an allocate of 2049 bytes may
return 2049 -- that's what you asked for -- but internally allocate
4096.

Or you may ask for 16MB, and get 4K now and the rest on a promise.
That's the difference between a reservation and a commit; you as an
application shouldn't have to keep track of what's what. That's the
job of the memory manager, and it knows the addresses and lengths
doled out without you telling it.

>
> > When the programmer calls ALLOCATE or RESIZE, he keeps track of the
> > size somewhere in his own program.
>
> Well that's stupid as well !
>
> You should only know that you got as much as you asked for, and use no
> more. And need to know nothing else ! IMHO.

That's also keeping track; either it's fixed or it isn't, but it has
an explicit usable length. And since neither freeing the memory or
resizing it should require you to tell the memory manager the length
(it should just ignore it anyway), why bother?

>
> Chris

Mark Wills

unread,
Jun 14, 2011, 1:54:09 PM6/14/11
to
On Jun 14, 6:44 pm, Alex McDonald <b...@rivadpm.com> wrote:

>
> Or you may ask for 16MB, and get 4K now and the rest on a promise.
> That's the difference between a reservation and a commit; you as an
> application shouldn't have to keep track of what's what. That's the
> job of the memory manager, and it knows the addresses and lengths
> doled out without you telling it.
>

So, you agree with Hugh's argument then? Hugh is arguing for more
intelligent memory management in the 200x standard.

I think there are arguments both ways... Intelligent 'under the
covers' memory management isn't really in the spirit of the Forth way.
That said, why not modernise Forth? Why not adopt some more
contemporary paradigms? More intelligent features might encourage some
traction among new-comers. If you've been brought up on Java, you'd be
horrified at the low level of Forth.

Mark

Alex McDonald

unread,
Jun 14, 2011, 2:07:28 PM6/14/11
to

Because memory management is not a feature of the Forth language,
although either scheme is implementable in Forth. Hugh is arguing for
a specific style of memory management with ALLOCATION, where the
allocator knows the length at a specific address. What should it reply
in the case of 16MB reserved and 4KB committed?

Zbiggy

unread,
Jun 14, 2011, 3:14:52 PM6/14/11
to
In comp.lang.forth, Mark Wills wrote:

> That said, why not modernise Forth? Why not adopt some more
> contemporary paradigms? More intelligent features might encourage some
> traction among new-comers. If you've been brought up on Java, you'd be
> horrified at the low level of Forth.

Well, I'm not quite sure, but if I properly understand, it could be
implemented by every Forth-variant-creator in his own Forth-implementation.
Why not? As I noticed, almost every Forth-variant has some unique
extensions.

If I understand the role of the "Forth 200x committee", they are defining
the "bare minimum". But everyone can extend such minimum on their own, while
designing own Forth compiler.

Such "bare minimum" I understand as "must have" for _every_ Forth (or for
every Forth-programmer) - from "big" compiler, to the one used on
microcontrollers. Is Hugh's proposal such "must have"? I don't know; not
enough experience (yet). But perhaps it can be done "on higher level",
I mean: just be written completely in Forth? If so - everyone could use such
word, in case of need including it into sources.
--
...but I'm ready to learn ('bout) of the power of Forth

Chris Hinsley

unread,
Jun 14, 2011, 3:21:16 PM6/14/11
to
>> I agree it's not likely, but you can't rule it out !
>
> It's totally likely that there are occurences where there some free
> space after an allocted area.
>
> - anton

I didn't mean that it was unlikely that you'd ever get a block with
some spare on the end, just that you couldn't allways know what the
allocator was going to do with it.

If the allocator _did_ return what it had allocated, then yes, you have
the 2 options you describe.

Having some under the hood way of finding the ammount allocated is just
asking for trouble. The allocator API either gives you the value or it
doesn't and you damb well stick to it !

Chris

BruceMcF

unread,
Jun 14, 2011, 5:13:42 PM6/14/11
to
On Jun 14, 2:02 am, Julian Fondren <ayrn...@gmail.com> wrote:

> > > VARIABLE ORIGINAL-ALLOCATE
> > > ' ALLOCATE  ORIGINAL-ALLOCATE !
> > > : ALLOCATE ( N -- A )
> > >         DUP CELL+ ORIGINAL-ALLOCATE
> > >         @ EXECUTE
> > >         TUCK ! CELL+
> > >         ;
>
> > This seems a long-winded way to:
>
> > : ALLOCATE ( n -- a )
> > DUP CELL+ ALLOCATE TUCK ! CELL+ ;
>
> ALLOCATE 's stack effect is ( u -- a-addr ior )

All the more important to avoid the unnecessary roundabout way of
executing the original ALLOCATE if the roundabout definition is also
wrong.

BruceMcF

unread,
Jun 14, 2011, 5:24:15 PM6/14/11
to
On Jun 14, 1:43 am, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
wrote:

> Can we wall this problem #4?  If Forth is like C in this regard,
> then the functionality is probably there, but hidden behind some
> old or new words.

Not necessarily. For example, the allocator is permitted to allocate
to the next nth power of two boundary (say, 16 bytes).

> E.g., from the poorly worded ANS specs, RESIZE could be understood
> to be *only* a *change* in size of the memory allocation.
> I.e., it would fail if the allocation was the same size.

Yes, the ANS Standard is not uniformly written to rule out all absurd
choices. However, there is likely a Turing problem in there ~ it is
probably impossible to write a spec that stands against deliberately
and willfully argumentative design choices irrespective of lack of any
benefit to the end user.

Hugh Aguilar

unread,
Jun 14, 2011, 8:03:26 PM6/14/11
to
On Jun 14, 12:01 am, Julian Fondren <ayrn...@gmail.com> wrote:
> Your proposal here is identical to your initial proposal, except that
> you've dropped your example from Current Practice, except that you've
> changed the name of the word.  So you've just ignored all of the
> discussion about it, the distinction that was made between ALLOCATION
> and ALLOCATED , the discussion of some current practice, of some
> implementation strategies.

I already said that what I'm presenting here is identical to what what
was presented and rejected earlier.

I'm not ignoring the distinction between ALLOCATION (what was
requested of ALLOCATE or RESIZE) and ALLOCATED (what was actually
allocated, which would be >= to what was requested) --- I just don't
think the distinction is particularly important. The whole point of
this was to support CLONE-LIST. I have lists which have nodes of
various types. To make a copy of the list, I need to be able to
determine the size of each node because CMOVE> needs this size. I
don't really care if the size I get from ALLOCATION is the same size
that I originally requested, or is slightly larger, because CMOVE>
will work either way. CMOVE> might be slightly slower if it is copying
not only the data but a "tail" of garbage as well, but that is not an
issue to me.

Currently in the novice package, I have rewritten all of the heap
memory words. The language is badly designed, else the application
programmer wouldn't be required to rewrite the basic functionality of
the language in order to support something as basic as linked lists. I
think the reason why there are so few Forth applications, is because
the Forthers spend way too much time dinking around with low-level
code that should have been provided already. This is also why Forth
applications are often hard to read --- because everybody implements
the low-level code differently from each other, and the programs seem
to be written in different languages --- "if you've seen one Forth,
you've seen one Forth."

Keeping track of the size of the nodes when the nodes are created,
doesn't work very well. The constructor for the node must call the
constructor for the parent type first. That parent constructor sets
the node-size field in the node to the wrong value (too small). The
constructor then has to manually fix this node-size field with the
correct size. That is the way that I did it originally, and it was a
huge hassle. It was error-prone because I could easily write a
constructor and forget to do this manual fix-up, and not know about
this bug until later on when (if) I tried to run CLONE-LIST on the
list containing the node and failed to copy the entire node. Forcing
the application programmer to do this manually is just clumsy --- this
is low-level code that should be part of the language.

Hugh Aguilar

unread,
Jun 14, 2011, 8:08:04 PM6/14/11
to
On Jun 13, 11:43 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
wrote:
> "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message

So far, you are the closest to getting a B grade --- buried in that
lengthy post was the correct answer as to one of the fundamental
principles of Forth-200x that my RfD violated. You didn't come right
out and say it though, so you don't get the B grade yet. Try again ---
you are almost there!

Hugh Aguilar

unread,
Jun 14, 2011, 8:19:45 PM6/14/11
to

You get a C --- you used the words "crap" and "stupid," and you didn't
say anything at all except that the programmer should just "know" how
much memory he asked for --- that pretty well fits my criteria for a C
grade. Look on the bright side though; at least you didn't get an F
like I did!

BruceMcF

unread,
Jun 14, 2011, 9:07:01 PM6/14/11
to
On Jun 14, 8:03 pm, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> The whole point of this was to support CLONE-LIST.

Of course, then anyone who wanted to use CLONE-LIST would be locked
into allocating a node at a time.

Hugh Aguilar

unread,
Jun 14, 2011, 9:25:30 PM6/14/11
to

Well, yeah! If you allocate memory for a list all at once either on
the heap or in the dictionary, then you have to do your own memory
management within that gigantic memory block --- that is definitely
doing things the hard way, considering that the language already has a
heap built in. What would be the point of that?

BruceMcF

unread,
Jun 14, 2011, 10:57:58 PM6/14/11
to

Except "the hard way" wouldn't be all that hard, after all, would it?
It would also localize memory allocation error recovery, rather than
scattering the response to memory allocation errors through each
iteration of a process. And freeing the list at the end is much
simpler, since its a FREE of the whole structure rather than walking
down a list, freeing as you go.

Not locking in means you can start out allocating as you go, and if it
ever becomes problematic, switch to allocating larger chunks, without
tying the system ability to determine the size of a node to a heap
allocation reporting word.

Rod Pemberton

unread,
Jun 15, 2011, 1:44:32 AM6/15/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:96d40311-938b-4b0c...@m24g2000yqc.googlegroups.com...

> On Jun 13, 11:43 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
> wrote:
> > "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message
> >
news:371d3747-5420-4260...@g28g2000yqa.googlegroups.com...
>
> > > Here is pop quiz to test
> > > [quiz info]
> >
> > [RP attempted to pass the quiz]

> >
> So far, you are the closest to getting a B grade ---

Ok.

> buried in that lengthy post was the correct
> answer as to one of the fundamental
> principles of Forth-200x that my RfD violated.
> You didn't come right out and say it though,
> so you don't get the B grade yet. Try again ---
> you are almost there!

Really? I may need to let it sit for a few days until my sarcasm level
increases ...

Did you hint at the answer in another reply? I.e., there is no sizeof() in
Forth?

OMG, please don't tell me you want a "SIZEOF" in Forth. It *never*
should've been part of C ... That's a really dark corner of C that should
be avoided. Unfortunately, use of malloc() basically necessitates its use.
ISTM, that Forth uses counted strings, anything other than a basic object
should be counted too. In which case, the "size of" every item in Forth
could/should be contained within the item itself. ANS has words like COUNT,
CHARS, CELLS, FLOATS, DFLOATS, SFLOATS, for basic objects, but I don't see
something for obtaining the size of a larger or structured items that would
be allocated out of or overlayed onto generic space, e.g., in C, a struct or
union with space from malloc(), or typedef. In your case, their is no
apparent way to sizeof() the node in the linked list which is stored in
generically allocated space ...


Rod Pemberton


Chris Hinsley

unread,
Jun 15, 2011, 5:43:13 AM6/15/11
to

Ha,Ha. :)

Chris

Alex McDonald

unread,
Jun 15, 2011, 5:52:22 AM6/15/11
to

This is a fundamental design problem in your code, not a problem with
the memory allocation words that Forth provides.

Many systems (Linux, BSD, every version of IBM mainframe systems to z/
OS and others) do not provide any mechanism for discovering this
length information. Here are the standard Linux kernel calls;

void *kmalloc( size_t size, int flags );
void kfree( const void *objp );

There isn't any way of getting what you want from the system.

Effectively, what you are trying to do is push off a problem in your
application code to a layer below you. That's not the correct
response, which should be either to (1) redesign to remove the problem
or (2) wrap the memory allocation functions -- effectively write your
own, as you have done -- to store the information your application
needs. That doesn't require an addition to the language
specification.

Mark Wills

unread,
Jun 15, 2011, 6:13:09 AM6/15/11
to

"because memory management is not a feature of the forth language..."

Agreed. At the moment it isn't. But the point is, a new standard is
being developed. Here's a chance to get out of the 70's and modernise
with new language features. These features don't have to be part of
core. They can be optional extensions.

Hugh Aguilar

unread,
Jun 15, 2011, 8:32:54 AM6/15/11
to
On Jun 14, 11:44 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>

I don't want a SIZEOF in Forth --- that would make no sense at all,
what with Forth being an untyped language.

Hugh Aguilar

unread,
Jun 15, 2011, 8:43:03 AM6/15/11
to

This business of the application programmer writing a memory
management system in high-level Forth is foolishness. It is a waste of
time for the application programmer to spend his time dinking around
with such low-level code. Also, being written in high-level Forth
rather than assembly language, it is going to be slow, which is a
problem because low-level code gets called quite a lot. Also, every
application programmer is going to do this differently, which makes
the programs hard to read.

You are making lists a lot more complicated than they need to be. What
about trees? Are you going to do your own memory management there too?
You are dumping way too much work on the application programmer ---
this is why there are so few Forth applications!

Alex McDonald

unread,
Jun 15, 2011, 8:59:34 AM6/15/11
to

There are two fundamental calls to any memory management system, out
of which all the rest can be built; allocate and free. Resize is a
nice to have to prevent excessive copying of blocks of data. Even
then, some memory management systems don't have support such an
operation. Some support it, but return a failure code if the operation
can't be performed. For those cases, allocate copy and free suffice.

Two words, a third for efficiency if the underlying system supports
it. That's all you need.

I can't see why any more than these would require to be *language
features. If they're optional extensions and built out of existing
Forth words, then this is a proposal for a *library. As an example,
see gc4image.fs in http://www.complang.tuwien.ac.at/forth/garbage-collection.zip,
where this library builds on ALLOCATE and FREE and provides only two
words, an ALLOC and COLLECT-GARBAGE, as a programmer interface. But
since Hugh has a clearly stated aversion to other people's code, a
library approach will probably not strike him as an acceptable
solution.

If we were discussing words like DUP that can't be expressed
effectively or efficiently in terms of other Forth words and
consequently need to be primitives, then I'd understand; but we're
not.


Hugh Aguilar

unread,
Jun 15, 2011, 9:10:37 AM6/15/11
to

And the first B grade goes to --- Alex McDonald!

I said at the beginning that my RfD violated *two* fundamental
principles of Forth-200x. This is the first principle violated:

1.) Gforth is written in C, and therefore it necessarily must have the
same limitations as C. The heap in C doesn't provide an ALLOCATION
function, and therefore the heap in Forth can't either.

The fundamental disagreement between myself and Anton Ertl, is that he
believes that Forth is a toy interpreter written in C, and I believe
that Forth is a real language that is *better* than C. This is why he
gives me an F grade in Forth-200x.

> There isn't any way of getting what you want from the system.

What a loser mentality! This reminds me of the old joke about the guy
who asked for directions to his goal and was told: "You can't get
there from here."

Other languages run under these same systems (BSD, Linux, Windows,
etc.), and yet they work just fine. Factor, for example, has its own
heap system --- it doesn't rely on MALLOC and all of that other
garbage that comes with C. So long as Forth-200x is designed with the
constraint that it must support C implementations such as Gforth, then
Forth-200x will always be nothing more than a C wannabe --- Forth will
never be considered to be a better language than C, which is what
Chuck Moore wanted Forth to be from the very beginning (and why I got
interested in Forth way back in 1984). The C language is just a big
mish-mash of bad design decisions --- and one of them is that the heap
lacks an ALLOCATION function --- but why should Forth inherit all of
C's problems?

I said at the beginning that there were *two* fundamental principles
of Forth-200x that my RfD violated. What was the other fundamental
principle violated? There is still room for another B grade to be
given out for the correct answer to this question.

Alex McDonald

unread,
Jun 15, 2011, 9:50:34 AM6/15/11
to

You are sadly mistaken on several counts. There is no mechanism to get
such information from many systems; please show me a system call that
returns the information (specifically, the length allocated). Windows,
BSD, Linux's SLAB SLOB SLUB.

I would like to see where Anton has ever said that Forth is a toy
interpreter; or are you making stuff up again?

>
> > There isn't any way of getting what you want from the system.
>
> What a loser mentality! This reminds me of the old joke about the guy
> who asked for directions to his goal and was told: "You can't get
> there from here."
>
> Other languages run under these same systems (BSD, Linux, Windows,
> etc.), and yet they work just fine. Factor, for example, has its own
> heap system --- it doesn't rely on MALLOC and all of that other
> garbage that comes with C.

AFAIK, Factor uses garbage collection, and it too has no way of
telling you what length you previously allocated at a specific
address. I'm struggling to think of a language (as opposed to library)
that does.

BYW, here's GC in Forth; http://www.complang.tuwien.ac.at/forth/garbage-collection.zip.
Oddly, it also runs on gforth, written in C.

> So long as Forth-200x is designed with the
> constraint that it must support C implementations such as Gforth, then
> Forth-200x will always be nothing more than a C wannabe --- Forth will
> never be considered to be a better language than C, which is what
> Chuck Moore wanted Forth to be from the very beginning (and why I got
> interested in Forth way back in 1984). The C language is just a big
> mish-mash of bad design decisions --- and one of them is that the heap
> lacks an ALLOCATION function --- but why should Forth inherit all of
> C's problems?

You really must start distinguishing between language and library.
Java is a very small language supported by a huge set of libraries,
and if you tried suggesting that feature X needs an addition to the
language specification, you would get shot down in flames. In fact, a
good language *minimizes language cruft, something that Chuck made
abundantly clear over the years.


>
> I said at the beginning that there were *two* fundamental principles
> of Forth-200x that my RfD violated. What was the other fundamental
> principle violated? There is still room for another B grade to be
> given out for the correct answer to this question.

Who cares? I certainly don't, since getting a B from someone who gets
an F is hardly rewarding.

Hugh Aguilar

unread,
Jun 15, 2011, 9:56:37 AM6/15/11
to

I'm okay with the heap being an optional extension --- ALLOCATE, FREE
and RESIZE already are in ANS-Forth --- a lot of micro-controllers
aren't big enough to support a heap, or a heap just doesn't make sense
for what the micro-controller is being used for.

I don't want the heap to be a library though, because libraries are
written in high-level standard Forth (my novice package being a good
example). The heap is very low-level fundamental code and should be
written in assembly-language for efficiency. The whole point of making
ALLOCATION part of the standard is to get away from the inefficient
Forth code that I already have available in the novice package. Also,
btw, when you write in Forth you are also inefficient in memory usage
because you are saving the memory-block size in a cell prepended to
the memory-block. This is redundant because the size is already being
stored internally (FREE and RESIZE access it). That extra cell per
memory-block can add up to a lot of memory when you have a large data
structure with thousands of nodes.

Hugh Aguilar

unread,
Jun 15, 2011, 10:06:25 AM6/15/11
to
On Jun 15, 7:50 am, Alex McDonald <b...@rivadpm.com> wrote:
> On Jun 15, 2:10 pm, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> > And the first B grade goes to --- Alex McDonald!
>
> > I said at the beginning that my RfD violated *two* fundamental
> > principles of Forth-200x. This is the first principle violated:
>
> > 1.) Gforth is written in C, and therefore it necessarily must have the
> > same limitations as C. The heap in C doesn't provide an ALLOCATION
> > function, and therefore the heap in Forth can't either.
>
> > The fundamental disagreement between myself and Anton Ertl, is that he
> > believes that Forth is a toy interpreter written in C, and I believe
> > that Forth is a real language that is *better* than C. This is why he
> > gives me an F grade in Forth-200x.
>
> You are sadly mistaken on several counts. There is no mechanism to get
> such information from many systems; please show me a system call that
> returns the information (specifically, the length allocated). Windows,
> BSD, Linux's SLAB SLOB SLUB.

There is no C language system call! The point that I'm making is that
you have to write your own heap, if you want to have a better heap
than the one provided by C --- you can't just rely on MALLOC in GLIBC.

> I would like to see where Anton has ever said that Forth is a toy
> interpreter; or are you making stuff up again?

Anton Ertl is committed to supporting Gforth, and Gforth is a toy
interpreter.

> > I said at the beginning that there were *two* fundamental principles
> > of Forth-200x that my RfD violated. What was the other fundamental
> > principle violated? There is still room for another B grade to be
> > given out for the correct answer to this question.
>
> Who cares? I certainly don't, since getting a B from someone who gets
> an F is hardly rewarding.

I said at the beginning that only Anton Ertl is qualified to give
grades --- he is the professor, after all. Your B grade is contingent
upon his approval.

If he refuses to give you the B grade however, then he will have to
explain how this can be consistent with his ongoing insistence that
Forth-200x support C implementations such as Gforth. I think that your
B grade is as rock-solid as my F grade --- but it is Anton Ertl's
decision in both cases.

Chris Hinsley

unread,
Jun 15, 2011, 10:18:30 AM6/15/11
to

Hey, he gave me a C. You said the same without useing the words
'stupid' or 'silly'. He's just wordist I tell you, marking me down like
that ! ;)

Chris

Chris Hinsley

unread,
Jun 15, 2011, 10:20:25 AM6/15/11
to

Hugh, you really need to take that pinecone out your arse !

Oh dear, I just made 'the list'. :)

Does that mean I've graduated somhow in the Forth newsgroup ?

Chris

Mark Wills

unread,
Jun 15, 2011, 10:22:07 AM6/15/11
to

Respectfully, you are sadly mistaken:

"You are sadly mistaken on several counts. There is no mechanism to
get
such information from many systems; please show me a system call that
returns the information (specifically, the length allocated). Windows,
BSD, Linux's SLAB SLOB SLUB. "

You are approaching this from the mind-set that Forth HAS to sit on
top of an operating system. It doesn't. And it was never intended to
by the language's creator all those years ago. Indeed Forth's ideal
'domain' isn't PC's and large systems at all. It's small embedded
systems, that don't need an operating system, as we all know. Surely,
the fact that a particular Forth system sits atop an OS is incidental?

Furthermore, you seem to be under the impression that an allocation of
memory in Forth is directly translated into an allocation at the OS
level. In other words, if one executes ALLOCATE then ALLOCATE executes
Malloc() or something similar. If the functionality you cite is not
available on your OS, then your Forth system can simply claim a chunk
of memory at startup, and ALLOCATE, FREE whatever will work internally
with this chunk of memory. Is this not how older Forth systems work,
claiming space from the dictionary with ALLOT?

Mark.

BruceMcF

unread,
Jun 15, 2011, 11:16:11 AM6/15/11
to
On Jun 15, 8:43 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> This business of the application programmer writing a memory
> management system in high-level Forth is foolishness.

Its pretty silly to try to paint a single floating pointer and an end
pointer as being as complex as complete memory management system, just
to try to win imaginary usenet news debating points ~ not as silly as
turning it into a soap opera and painting Anton Ertl as the villain of
the piece, but pretty silly, nonetheless.


BruceMcF

unread,
Jun 15, 2011, 11:35:15 AM6/15/11
to
On Jun 15, 10:22 am, Mark Wills <markrobertwi...@yahoo.co.uk> wrote:
> "You are sadly mistaken on several counts. There is no mechanism
> to get such information from many systems; please show me a
> system call that returns the information (specifically, the
> length allocated). Windows, BSD, Linux's SLAB SLOB SLUB. "

> You are approaching this from the mind-set that Forth HAS to sit on
> top of an operating system.

No, its not. Bear in mind that Hugh is not presenting what he finds to
be a useful capability and a means of adding it to a specific system
he uses, but is rather demanding that the capability be made part of
the standard.

When proposing a word for the standard, both implementations running
alongside other programs in an external operating and implementations
running on the bare metal have to be taken into account.

If proposing it for a library, there is no 'proposing' to do.big work
to do, just define a compiler constant:

[HAS?] allocated? [IF]
: node-allocate ( u -- a ior ) ALLOCATE ;
: node-size ( a -- u ) ALLOCATED ;
[ELSE]
: node-allocate ( u -- a ior )
DUP CELL+ >R ALLOCATE DUP IF 0 ELSE ROT THEN R> ! ;
: node-size ( a -- u ) 1 CELLS - @ ;
[THEN]

... and any target implementation where ALLOCATED can be worked out,
just include the definition for ALLOCATED in the prelude for that
implementation, and define allocation? as true in the compiler
constant vocabulary.

Stephen Pelc

unread,
Jun 15, 2011, 12:23:28 PM6/15/11
to
On Wed, 15 Jun 2011 06:56:37 -0700 (PDT), Hugh Aguilar
<hughag...@yahoo.com> wrote:

>I don't want the heap to be a library though, because libraries are
>written in high-level standard Forth (my novice package being a good
>example). The heap is very low-level fundamental code and should be
>written in assembly-language for efficiency.

The MPE embedded heap has been entirely in high-level for 15 years
or so. Heap performance has not been an issue with the VFX code
generator.

On the desktop, we have only found one occasion on which using the
system heap made any difference. The solution was to change the
way we interfaced to the system heap. The occasion was (AFAIR)
the Sandmark benchmark.

If your code is too slow, you have two options:
1) Rewrite the code to use the heap less often.
2) Change your compiler.

Option 1 is standard practice in the C world. Writing a good,
fast heap is non-trivial and I certainly would not do it in
assembler. Wring a sub-heap for application-specific purposes
is common practice.

Stephen

--
Stephen Pelc, steph...@mpeforth.com
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeforth.com - free VFX Forth downloads

Alex McDonald

unread,
Jun 15, 2011, 12:24:36 PM6/15/11
to

No, that is not my point. As a *design point, OSes do not provide the
length of an allocated block. As a *design point, Forth's ALLOCATE
does not return this information either, nor do several other
languages, including C. It is, to be frank, superfluous, since
generations of programmers at all levels have managed without such a
feature. Those that can't are free to augment whatever memory
management scheme they wish to use.

Alex McDonald

unread,
Jun 15, 2011, 12:52:04 PM6/15/11
to

A couple of points;

You're assuming that the length is stored. In SLAB-like allocators it
may not be stored since every allocation from that slab has the same
length.

Since requesting the length of an address is possible in either case,
stored or not, you need to look at the overhead of requesting the
information. It may be significant; in fact, as significant as the
allocation or freeing of the memory. Given that it may require locking
of structures in async/MP environments, running lists where data may
be out of cache etc etc, doing so would be undesirable.

It's certainly not free, and in most cases probably not worth the
trade off of the minor overhead of a cell per allocation.

Alex McDonald

unread,
Jun 15, 2011, 1:12:51 PM6/15/11
to
On Jun 15, 3:06 pm, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> On Jun 15, 7:50 am, Alex McDonald <b...@rivadpm.com> wrote:
>
>
>
>
>
>
>
>
>
> > On Jun 15, 2:10 pm, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> > > And the first B grade goes to --- Alex McDonald!
>
> > > I said at the beginning that my RfD violated *two* fundamental
> > > principles of Forth-200x. This is the first principle violated:
>
> > > 1.) Gforth is written in C, and therefore it necessarily must have the
> > > same limitations as C. The heap in C doesn't provide an ALLOCATION
> > > function, and therefore the heap in Forth can't either.
>
> > > The fundamental disagreement between myself and Anton Ertl, is that he
> > > believes that Forth is a toy interpreter written in C, and I believe
> > > that Forth is a real language that is *better* than C. This is why he
> > > gives me an F grade in Forth-200x.
>
> > You are sadly mistaken on several counts. There is no mechanism to get
> > such information from many systems; please show me a system call that
> > returns the information (specifically, the length allocated). Windows,
> > BSD, Linux's SLAB SLOB SLUB.
>
> There is no C language system call! The point that I'm making is that
> you have to write your own heap, if you want to have a better heap
> than the one provided by C --- you can't just rely on MALLOC in GLIBC.
>
> > I would like to see where Anton has ever said that Forth is a toy
> > interpreter; or are you making stuff up again?
>
> Anton Ertl is committed to supporting Gforth, and Gforth is a toy
> interpreter.

So Anton Ertl in fact does not believe that gforth is a toy
interpreter; you do. Presenting it as though that was his position is
dishonest. Please strive for a little more accuracy and a little less
attacking of individuals.

>
> > > I said at the beginning that there were *two* fundamental principles
> > > of Forth-200x that my RfD violated. What was the other fundamental
> > > principle violated? There is still room for another B grade to be
> > > given out for the correct answer to this question.
>
> > Who cares? I certainly don't, since getting a B from someone who gets
> > an F is hardly rewarding.
>
> I said at the beginning that only Anton Ertl is qualified to give
> grades --- he is the professor, after all. Your B grade is contingent
> upon his approval.
>
> If he refuses to give you the B grade however, then he will have to
> explain how this can be consistent with his ongoing insistence that
> Forth-200x support C implementations such as Gforth. I think that your
> B grade is as rock-solid as my F grade --- but it is Anton Ertl's
> decision in both cases.

The gradings are yours alone. I think your F is rock solid though.

Elko T

unread,
Jun 15, 2011, 3:16:37 PM6/15/11
to
Alex McDonald wrote:
> On Jun 15, 1:03 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>> On Jun 14, 12:01 am, Julian Fondren <ayrn...@gmail.com> wrote:
>>
>>> Your proposal here is identical to your initial proposal, except that
>>> you've dropped your example from Current Practice, except that you've
>>> changed the name of the word. So you've just ignored all of the
>>> discussion about it, the distinction that was made between ALLOCATION
>>> and ALLOCATED , the discussion of some current practice, of some
>>> implementation strategies.
>>
>> I already said that what I'm presenting here is identical to what what
>> was presented and rejected earlier.
>
> This is a fundamental design problem in your code, not a problem with
> the memory allocation words that Forth provides.
>
> Many systems (Linux, BSD, every version of IBM mainframe systems to z/
> OS and others) do not provide any mechanism for discovering this
> length information. Here are the standard Linux kernel calls;
>
> void *kmalloc( size_t size, int flags );
> void kfree( const void *objp );
>
> There isn't any way of getting what you want from the system.
>
> Effectively, what you are trying to do is push off a problem in your
> application code to a layer below you. That's not the correct
> response, which should be either to (1) redesign to remove the problem
> or (2) wrap the memory allocation functions -- effectively write your
> own, as you have done -- to store the information your application
> needs. That doesn't require an addition to the language
> specification.

This answer gets an A from me. And I confirm Hugh's F. (I'm not a
professor at the moment, but I do evaluations of people's
contributions to IEEE journals, so I think I'm in line. :) )

The situation is exactly as Alex wrote. Moreover, I personally have
not found any need for the requested functionality. I *have* written
my own memory manager, overloading the system's ALLOCATE etc, and even
though I could, therefore, provide an ALLOCATED word, I haven't done
so. I never needed it. Looking at the mem-manager code, I see that I
even don't have a word with such a function, although I have its factors.
[The reason I wrote that package was that Win32Forth at the time
('95-'96) had a very slow memory manager. It was building a list of
the allocations and was searching through it for the deletions, IIRC,
and that was *the* bottleneck when doing millions of them. I believe
it's fixed now. I continue using it, because it has some extra
features that are very handy - setting the total allocatable size, and
returning data on how much of it is actually used. That helps when
running many experiments on a multi-CPU machine, to ensure that they
all fit in physical memory and avoid swapping and thrashing.]

--
No, no, you can't e-mail me with the nono.

Rod Pemberton

unread,
Jun 15, 2011, 4:11:59 PM6/15/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:109a81e4-5fbf-455d...@e35g2000yqc.googlegroups.com...

>
> I have lists which have nodes of various types. To make a copy
> of the list, I need to be able to determine the size of each node
> because CMOVE> needs this size.

I thought you just said you didn't want a SIZEOF in Forth. Now, I'm
confused ... ;-)

> [...] I have rewritten all of the heap memory words. The language


> is badly designed, else the application programmer wouldn't be
> required to rewrite the basic functionality of the language in order
> to support something as basic as linked lists.

Oh, Hugh, you know they are just going to say: "You don't understand Forth
yet. You're still thinking like a non-Forther." Oh, sorry, I guess that
was me. Lol.

> I think the reason why there are so few Forth applications, is because
> the Forthers spend way too much time dinking around with low-level
> code that should have been provided already.

What language provides support for linked-lists? LISP?

> This is also why Forth applications are often hard to read --- because
> everybody implements the low-level code differently from each other,
> and the programs seem to be written in different languages --- "if
> you've seen one Forth, you've seen one Forth."

Lack of syntax ... no structure, IMO, or only what a programmer
chooses to apply.

> Keeping track of the size of the nodes when the nodes are
> created, doesn't work very well.

Are these nodes of different sizes!?!? No!!!! Use fixed size nodes.

If some data element is not of a fixed size, store a pointer in the node for
that data element. Store the data element in a stack (or "dictionary")
which has all of the differently sized data of that same item. You don't
need to store all the data in each node. You just need to be able to locate
it. The node should just be a few data items, mostly pointers: for the
links, to data, etc. Well, that's a suggestion from a C programmer ...


Rod Pemberton

Rod Pemberton

unread,
Jun 15, 2011, 4:16:33 PM6/15/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:dc40449b-6366-44d5...@r35g2000prj.googlegroups.com...

> On Jun 15, 3:52 am, Alex McDonald <b...@rivadpm.com> wrote:
> > On Jun 15, 1:03 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>

> > > Keeping track of the size of the nodes when the nodes are created,

> > > doesn't work very well. [...]


>
> > This is a fundamental design problem in your code, not a problem with
> > the memory allocation words that Forth provides.
>
> > Many systems (Linux, BSD, every version of IBM mainframe systems to z/
> > OS and others) do not provide any mechanism for discovering this
> > length information. Here are the standard Linux kernel calls;

> > [...]


>
> > There isn't any way of getting what you want from the system.
>
> > Effectively, what you are trying to do is push off a problem in your
> > application code to a layer below you. That's not the correct
> > response, which should be either to (1) redesign to remove the problem
> > or (2) wrap the memory allocation functions -- effectively write your
> > own, as you have done -- to store the information your application
> > needs. That doesn't require an addition to the language
> > specification.
>
> And the first B grade goes to --- Alex McDonald!

Huh? Oh, yeah, almost a B ... :)

> I said at the beginning that my RfD violated *two* fundamental
> principles of Forth-200x. This is the first principle violated:
>
> 1.) Gforth is written in C, and therefore it necessarily must have the
> same limitations as C. The heap in C doesn't provide an ALLOCATION
> function, and therefore the heap in Forth can't either.

C has alloca(). It's just not standard. The C standards don't require the
use of a heap or stack. That's why alloca() is not standard. There was at
least one C implementation that didn't use a stack.

Forth requires stacks. So, there is no fundamental reason to not use it,
except maybe speed ... Stack operations other than on the top few levels of
the stack are expensive, both in Forth and on most microprocessors in the
way that Forth uses the stack at depth (shifting, inserting, deleting):
PICK, ROLL, etc.

> > There isn't any way of getting what you want from the system.
>

> What a loser mentality! [...]


>
> Other languages run under these same systems (BSD, Linux, Windows,
> etc.), and yet they work just fine. Factor, for example, has its own
> heap system --- it doesn't rely on MALLOC and all of that other
> garbage that comes with C.

Many C programs have their own memory allocator. There are at least three
common publicly available memory allocators for C applications. They use
malloc() to allocate a large chunk of memory, then use their own allocator
against that block of memory. AIUI, there is no reason why you cannot do
this in Forth. Just prior to posting, Elko T said he did just that.

FYI, many C implementations had problems with not having the size of the
allocated memory block readily available. The user didn't need the info,
but the compiler and executable did. The "common" solution was to put a
header on the allocated memory block just prior to the address returned as
the start of the allocated memory region. A negative offset from the
allocated address is used to access the header by memory related code. The
hidden header contains the size of the memory block allocated. But, this is
not standardized either. Implementing functions like realloc() in pure C,
without such hidden operations, is almost impossible.

> So long as Forth-200x is designed with the
> constraint that it must support C implementations such as Gforth, then
> Forth-200x will always be nothing more than a C wannabe

Portability or constraint?

I guess it depends on your perspective. There are lots of constraints,
er... portable, features in the C spec's that no longer apply to most modern
C implementations.

C has lots of "warts" too. That's because the language was used in real
world systems and extended and changed over time. Forth was too. Most
aren't. Most were designed by an academic or group: Pascal, Fortran, COBOL,
PL/1, BASIC ...

> Forth will never be considered to be a better language than C

Is that due to the memory allocator? I don't think so ...

That's a big leap, BTW, from problems with a memory allocator to Forth being
constrained, er... made portable, by C implementations. :-)

I think this is much more related to Forth syntax (none) and use of stacks.
The language has no structure except what you give it. AFAIR, Forth is the
_only_ HLL language I've used where I must use a stack and have to keep
track of stuff on the stack in my head. Most languages use variables which
the compiler keeps track of and relocates as needed between memory, stack,
and registers. Forth has variables, but ISTM that Forth programmers are not
keen on their use. If or when they use them, they seem to prefer to move
the variable to the stack, manipulate data on the stack, store data back
into variable. Forth is perfectly capable of directly manipulating
variables in memory, via words like TOGGLE and PLUSSTORE +! . I.e., you
should be able to directly add, subtract, multiply, divide, and, or, xor,
directly on the variable, IMO. If Forth programmers did that, programming
in Forth would be much more like other HLLs. In which case, more people
might program in Forth. If you didn't see it, I was discussing such
operations in my "common sequences" thread.


Rod Pemberton

Rod Pemberton

unread,
Jun 15, 2011, 4:20:06 PM6/15/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:99dc2e42-9bce-422d...@d26g2000prn.googlegroups.com...
> I don't want a SIZEOF in Forth --- that would make no sense at all,
> what with Forth being an untyped language.
>

Funny! Sarcastic, but funny. :-)

Wait ... You were being sarcastic, right? If not, what are strings, chars,
cells, floats, dfloats, sfloats, if not types? Excluding more complicated
types, the Forth words above function as sizeof() on a specific type:
sizeof(type).


Rod Pemberton

van...@vsta.org

unread,
Jun 15, 2011, 5:09:51 PM6/15/11
to
Rod Pemberton <do_no...@noavailemail.cmm> wrote:
> Wait ... You were being sarcastic, right? If not, what are strings, chars,
> cells, floats, dfloats, sfloats, if not types? Excluding more complicated
> types, the Forth words above function as sizeof() on a specific type:
> sizeof(type).

sizeof() is polymorphic on its argument. He's quite correct; given a storage
pointer in Forth there is no generic, polymorphic way to determine its type,
thus no way to answer the sizeof() question. You have to have a priori
knowledge of the storage under that pointer, and answer based on that a
priori knowledge.

When you carry the knowledge of the type of some memory under a storage
address in your head, rather than having the compiler calculate it (or the
object itself have self-describing fields), we call that language "untyped".
Having the compiler keep track makes for more complicated languages (with
more complicated compilers). Having each object be self-describing creates
more run-time overhead. Forth does neither, and thus can have a simple
compiler with low runtime overhead. In exchange, you keep track of the types
of things yourself, because the system doesn't.

--
Andy Valencia
Home page: http://www.vsta.org/andy/
To contact me: http://www.vsta.org/contact/andy.html

Hugh Aguilar

unread,
Jun 15, 2011, 7:18:02 PM6/15/11
to
On Jun 15, 2:11 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
wrote:
> "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message

>
> news:109a81e4-5fbf-455d...@e35g2000yqc.googlegroups.com...
>
>
>
> > I have lists which have nodes of various types. To make a copy
> > of the list, I need to be able to determine the size of each node
> > because CMOVE> needs this size.
>
> I thought you just said you didn't want a SIZEOF in Forth.  Now, I'm
> confused ... ;-)

You wouldn't be so confused if you were more cognizant of the
distinction between compile-time and run-time. (Well, maybe you would
be confused anyway, as that seems to be your natural state. ;-)

C's SIZEOF works at compile time because all of the variables have a
declared type. This includes both primitive types (int, float, etc.)
and user-defined struct types. SIZEOF can reckon their size at compile-
time, and this value is treated as a constant by the compiler.

By comparison, my ALLOCATION works at run-time. When this function
runs it determines the size of the memory-block (which typically
contains a struct) by reading a cell (typically prepended to the
memory-block) that contains the size datum.

In an untyped language such as Forth, you have to figure this out at
run-time, because there are no declarations at compile-time to clue in
the compiler.

> > Keeping track of the size of the nodes when the nodes are
> > created, doesn't work very well.
>
> Are these nodes of different sizes!?!?  No!!!!  Use fixed size nodes.

I think that this is the crux of the consternation. I don't assume
that every node in a data structure (list, tree, etc.) will be the
same type. It often happens that I start out writing the program and
it is fairly simple, with a big data structure containing nodes all of
the same type. Then things get more complicated. I have to implement
one or more child types to this data type, each of which is a (larger)
different size. Now I have a data structure containing nodes of
different sizes. If CLONE-LIST (in the case of linked list) is going
to be able to make a copy of this data structure, then it has to be
able to determine the size of each node.

I think that a lot of Forthers have only written fairly simple
programs that never got beyond the stage in which all of the node in
the data structure were of the same type (and this is true of most C
programmers too). When Bruce McFarland advocates using ALLOCATE to
obtain a gigantic memory-block, and then doing his own memory
management within that memory-block, he is assuming that all the nodes
are going to be the same size. This is not robust programming! What is
going to happen when his program gets more complicated (as described
above) and he needs to define one or more child types? He is going to
find himself up S. Creek in a wire boat with a cardboard paddle ---
that is what is going to happen!

> If some data element is not of a fixed size, store a pointer in the node for
> that data element.  Store the data element in a stack (or "dictionary")
> which has all of the differently sized data of that same item.  You don't
> need to store all the data in each node.  You just need to be able to locate
> it.  The node should just be a few data items, mostly pointers: for the
> links, to data, etc.  Well, that's a suggestion from a C programmer ...

This isn't going to work in the case of child data-types being
intermixed with parent data-types in a data structure. You are only
considering the case in which one of the fields of the data-type is of
a variable size (typically a string), in which case you can solve the
problem by making the field a one-cell pointer and the data (the
string) an allocated memory-block elsewhere in the heap. I already do
that routinely, but that has little or nothing to do with the issue of
having different data-types in the same data structure.

Hugh Aguilar

unread,
Jun 15, 2011, 7:22:21 PM6/15/11
to
On Jun 15, 3:09 pm, van...@vsta.org wrote:

This is true --- this is what I was describing in the last post
directed at Rob Pemberton in regard to the distinction between compile-
time and run-time.

Hugh Aguilar

unread,
Jun 15, 2011, 7:36:28 PM6/15/11
to
On Jun 15, 8:22 am, Mark Wills <markrobertwi...@yahoo.co.uk> wrote:
> You are approaching this from the mind-set that Forth HAS to sit on
> top of an operating system. It doesn't. And it was never intended to
> by the language's creator all those years ago. Indeed Forth's ideal
> 'domain' isn't PC's and large systems at all. It's small embedded
> systems, that don't need an operating system, as we all know. Surely,
> the fact that a particular Forth system sits atop an OS is incidental?

I see the primary target domain of Forth to be mid-size micro-
controllers. Forth isn't a very good choice for small micro-
controllers (4K program memory, 128 bytes data memory), and it isn't a
good choice for big 32-bit micro-controllers that run Embedded Linux
and are programmed in C++ or Java or whatever (even in Factor, if
Slava Pestov has his way).

Forth should primarily be focused on mid-sized micro-controllers (64K
program memory, 8K data memory). This is the Goldilocks micro-
controller --- big enough to support Forth, but not big enough to
support C++. This is why I'm interested in the PIC24 series --- it is
right in the middle of Forth's sweet spot. When I first read about the
PIC24 I was just as excited as I would have been if I had found a
planet that was the right distance from its sun to have liquid water!

Supporting desktop Forth systems is very secondary. Realistically, it
is too late for Forth to compete against the myriad high-level
languages available on desktop computers (Common Lisp, Ruby, Python,
etc., etc.) As far as I'm concerned, the only reason why we should
support Forth on desktop computers at all, is so that we can have
cross-compilers for micro-controllers --- micro-controller programming
is the only meaningful thing that we can do with Forth.

Rod Pemberton

unread,
Jun 16, 2011, 1:57:17 AM6/16/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:a9913560-e64d-47e2...@c41g2000yqm.googlegroups.com...

>
> You wouldn't be so confused if you were more cognizant of the
> distinction between compile-time and run-time.
>

I'm a C programmer. I'm aware of both. You're a Forth programmer. You
should be aware of neither, especially if you're an interpreted Forth
programmer. AIUI, even if you are a compiled Forth programmer, you
still shouldn't need to concern yourself with this. Compiled Forth should
work the same as interpreted Forth.

> C's SIZEOF works at compile time because all of the variables have a
> declared type. This includes both primitive types (int, float, etc.)
> and user-defined struct types. SIZEOF can reckon their size at compile-
> time, and this value is treated as a constant by the compiler.
>
> By comparison, my ALLOCATION works at run-time.

Why?

I mean, C does what you're wanting to do and there is no need for this in C.
So, why is there a need for this in Forth?

> ... my ALLOCATION works at run-time. When this function


> runs it determines the size of the memory-block (which typically
> contains a struct) by reading a cell (typically prepended to the
> memory-block) that contains the size datum.

Your struct is in implemented in Forth, in advance, and is known at compile
time. So, it's size should be known or determinable, by you or the Forth
environment.

> In an untyped language such as Forth, you have to figure this out at
> run-time, because there are no declarations at compile-time to clue
> in the compiler.

Unfortunately, my answer depends on the answer to the following questions:
How are struct's implemented in Forth?
What binds the struct together as a unit?
What allows access to struct items?

I suspect the answer is that a Forth word, probably using CREATE ... DOES> ,
allocates the space for a struct and creates the named struct. The named
struct places it address on the stack, just like a Forth variable, when
executed. Then, other Forth words have hardcoded offsets used to access the
struct items relative to the address for the struct in question. If so,
there should also be a Forth word that puts the size of the struct on the
stack. In which case, there is no need whatsoever for run-time
functionality.

> > > Keeping track of the size of the nodes when the nodes are
> > > created, doesn't work very well.
>
> > Are these nodes of different sizes!?!? No!!!! Use fixed size nodes.
>
> I think that this is the crux of the consternation. I don't assume
> that every node in a data structure (list, tree, etc.) will be the
> same type. It often happens that I start out writing the program and
> it is fairly simple, with a big data structure containing nodes all of
> the same type. Then things get more complicated.

Ok, I don't know what Forth does for this.

C has "union" for this. The same storage space is declared for use with
different items. E.g., for linked-lists, it's common in C to have a
different item depending on the node type stored in the same location of the
node. In one node, that location may contain an integer, in another a
float. The type of node is usually a numeric value stored in the node as a
char used indicate the node - like count for Forth strings. The node type
is used to determine how that location is accessed.

> Then things get more complicated. I have to implement
> one or more child types to this data type, each of which is a (larger)
> different size. Now I have a data structure containing nodes of
> different sizes. If CLONE-LIST (in the case of linked list) is going
> to be able to make a copy of this data structure, then it has to be
> able to determine the size of each node.

Use fixed size nodes.

> I think that a lot of Forthers have only written fairly simple


> programs that never got beyond the stage in which all of the node in
> the data structure were of the same type (and this is true of most C
> programmers too).

If there is no need, why do?

> > If some data element is not of a fixed size, store a pointer in the node
> > for that data element. Store the data element in a stack (or
> > "dictionary") which has all of the differently sized data of that same
> > item. You don't need to store all the data in each node. You just
> > need to be able to locate it. The node should just be a few data
> > items, mostly pointers: for the links, to data, etc. Well, that's a
> > suggestion from a C programmer ...
>
> This isn't going to work in the case of child data-types being
> intermixed with parent data-types in a data structure.

Don't do that. That really is the solution.

> You are only
> considering the case in which one of the fields of the data-type is of
> a variable size (typically a string), in which case you can solve the
> problem by making the field a one-cell pointer and the data (the
> string) an allocated memory-block elsewhere in the heap. I already do
> that routinely, but that has little or nothing to do with the issue of
> having different data-types in the same data structure.

I think you need to learn about C's "union" keyword.


Rod Pemberton

Elizabeth D Rather

unread,
Jun 16, 2011, 2:35:50 AM6/16/11
to
On 6/15/11 7:57 PM, Rod Pemberton wrote:
> "Hugh Aguilar"<hughag...@yahoo.com> wrote in message
> news:a9913560-e64d-47e2...@c41g2000yqm.googlegroups.com...
>>
>> You wouldn't be so confused if you were more cognizant of the
>> distinction between compile-time and run-time.
>>
>
> I'm a C programmer. I'm aware of both. You're a Forth programmer. You
> should be aware of neither, especially if you're an interpreted Forth
> programmer. AIUI, even if you are a compiled Forth programmer, you
> still shouldn't need to concern yourself with this. Compiled Forth should
> work the same as interpreted Forth.

ITC and DTC Forth implementations have the same distinction between
compile time and run time as compile-to-code Forths, even though
precisely what happens at compile time is somewhat different.

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."
==================================================

Alex McDonald

unread,
Jun 16, 2011, 5:45:47 AM6/16/11
to
On Jun 16, 12:18 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> On Jun 15, 2:11 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
> wrote:
>
> > "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message
>
> >news:109a81e4-5fbf-455d...@e35g2000yqc.googlegroups.com...
>
> > > I have lists which have nodes of various types. To make a copy
> > > of the list, I need to be able to determine the size of each node
> > > because CMOVE> needs this size.
>
> > I thought you just said you didn't want a SIZEOF in Forth.  Now, I'm
> > confused ... ;-)
>
> You wouldn't be so confused if you were more cognizant of the
> distinction between compile-time and run-time. (Well, maybe you would
> be confused anyway, as that seems to be your natural state. ;-)
>
> C's SIZEOF works at compile time because all of the variables have a
> declared type. This includes both primitive types (int, float, etc.)
> and user-defined struct types. SIZEOF can reckon their size at compile-
> time, and this value is treated as a constant by the compiler.
>
> By comparison, my ALLOCATION works at run-time. When this function
> runs it determines the size of the memory-block (which typically
> contains a struct) by reading a cell (typically prepended to the
> memory-block) that contains the size datum.
>
> In an untyped language such as Forth, you have to figure this out at
> run-time, because there are no declarations at compile-time to clue in
> the compiler.

create node here 0 , 10 c, 5 c, 20 , 30 ,
here swap - constant node-len

( or use Forth200x begin-structure node-len ... )

: copy-node ( in -- out )
[ node-len ] literal
dup allocate abort" error"
dup>r swap cmove r> ;

The length is compile time. Typing has nothing to do with determining
the length.

That is back to design, and is not a failing of the language or the
lack of a built-in function to give you the length of the structure.

Anton Ertl

unread,
Jun 16, 2011, 9:45:22 AM6/16/11
to
Chris Hinsley <chris....@gmail.com> writes:
>Having some under the hood way of finding the ammount allocated is just
>asking for trouble. The allocator API either gives you the value or it
>doesn't and you damb well stick to it !

Yes, but what the original discussion was about (and what I am still
discussing) is whether the API should be extended to provide this
feature. While some others claim that it is totally useless, I think
there are occasions where it is useful, and in principle ALLOCATED
could be implemented at less cost than by tacking on a cell the way a
library-level extension would.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2010: http://www.euroforth.org/ef10/

Anton Ertl

unread,
Jun 16, 2011, 9:53:04 AM6/16/11
to
van...@vsta.org writes:
>When you carry the knowledge of the type of some memory under a storage
>address in your head, rather than having the compiler calculate it (or the
>object itself have self-describing fields), we call that language "untyped".

Who are you?

I have seen many uses of "untyped" for a wide range of programming
languages with very different types and type checking, from C through
Lisp to Forth. Given that all these languages have types, and there
is no common meaning in the usage of "untyped" (e.g., a fan of
language A calls language B untyped, whereas a fan of languag B would
deny that, but calls language C "untyped"), I don't think that
"untyped" has any place in a serious discussion. It just means that
the person using that word does not know much about the language
except that it deals with types in a way different from what the
person prefers.

Mark Wills

unread,
Jun 16, 2011, 10:42:14 AM6/16/11
to
On Jun 16, 2:45 pm, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:

Indeed.

This, from ANS94 documents (A.1.3.1 Wordsets):

"From the beginning, the X3J14 Technical Committee faced not only
conflicting ideas as to what real Forth is, but also conflicting needs
of the various groups within the Forth community. At one extreme were
those who pressed for a bare Forth. At the other extreme were those
who wanted a fat Forth. Many were somewhere in between. All were
convinced of the rightness of their own position and of the wrongness
of at least one of the two extremes. The committee's composition
reflected this full range of interests.

The approach we have taken is to define a Core word set establishing a
greatest lower bound for required system functionality and to provide
a portfolio of optional word sets for special purposes. This simple
approach parallels the fundamental nature of Forth as an extensible
language, and thereby achieves a kind of meta-extensibility.

With this key, high-level compromise, regardless of the actual makeup
of the individual word sets, a firm and workable framework is
established for the long term. One may or may not agree that there
should be a Locals word set, or that the word COMPILE, belongs in the
Core Extensions word set. But at least there is a mechanism whereby
such things can be included in a logical and orderly manner."

Here here. Given this, I would think Hugh's suggestion is a good
candidate for inclusion in an optional word-set. I note his first post
in this thread recommended the option memory allocation word-set.

Mark

Alex McDonald

unread,
Jun 16, 2011, 12:57:23 PM6/16/11
to
On Jun 16, 2:45 pm, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:
> Chris Hinsley <chris.hins...@gmail.com> writes:
> >Having some under the hood way of finding the ammount allocated is just
> >asking for trouble. The allocator API either gives you the value or it
> >doesn't and you damb well stick to it !
>
> Yes, but what the original discussion was about (and what I am still
> discussing) is whether the API should be extended to provide this
> feature.  While some others claim that it is totally useless, I think
> there are occasions where it is useful, and in principle ALLOCATED
> could be implemented at less cost than by tacking on a cell the way a
> library-level extension would.

In my defence (since I've been the most vocal in this thread
suggesting ALLOCATED an unnecessary embellishment) I'm not claiming
that it's totally useless; that's not my position. I can think of
several scenarios where it has merit (such as debugging), but I
struggle to think of any that fall into the application domain. When
dealing with dynamically allocated memory, there are choices;

. Ensure items are of a known length at compile time
. Store the length requested, either in the allocated memory itself or
elsewhere; and ensure that it is cheaply recoverable
. Garbage collect
. Depend on the underlying support infrastructure to retrieve the
information (such as the OS)
. Leave the problem for the compiler or library writer

Are there others? I've put them in the order of my preference. I can't
see why this would require to be *language feature, optional wordset
or otherwise, since the use cases for this are limited to specific
areas where cost just doesn't matter and library code will do just as
well, and more transparently too.

An unscientific observation; wWhen I think about all the code I've
written over the years, I can't think of one occasion I've been forced
or wanted to get the length of something my code allocated. Yes,
perhaps when I have been passed an address of some variable length
data and I would like to know the length of it, but haven't been
supplied it; but that's just a deficiency in the coding skills of the
person that wrote the code that passed me the data. I would never
write such a call.

(As an aside, I owe Hugh an apology for claiming no OS I knew of
supported such a construct. Windows at least provides HeapSize (the
length of the allocated address) and a HeapWalk function. Both are
expensive to call, however, as the calls by default take locks on the
heap structures as they traverse them.)

Alex McDonald

unread,
Jun 16, 2011, 1:24:51 PM6/16/11
to

If this was to make it into Forth200x, I wouldn't use it. Anyone who
needs such a thing can do the following in their own Win32Forth v6
code as of today;


Version: 6.14.00 Build: 4
...
: allocated ( a -- n ) 4 cells - 0 call GetProcessHeap call
HeapSize ; ok
200 allocate drop allocated .s [1] 232 ok.

Chris Hinsley

unread,
Jun 16, 2011, 2:42:55 PM6/16/11
to
On 2011-06-16 14:45:22 +0100, Anton Ertl said:

> Chris Hinsley <chris....@gmail.com> writes:
>> Having some under the hood way of finding the ammount allocated is just
>> asking for trouble. The allocator API either gives you the value or it
>> doesn't and you damb well stick to it !
>
> Yes, but what the original discussion was about (and what I am still
> discussing) is whether the API should be extended to provide this
> feature. While some others claim that it is totally useless, I think
> there are occasions where it is useful, and in principle ALLOCATED
> could be implemented at less cost than by tacking on a cell the way a
> library-level extension would.
>
> - anton

From my own practical experience, I've tried it both ways. Taos had
swappable memory allocators that you could build in as you required
depending on the application or platform you had to cope with. And we
had a _lot_ of different ones we provided to choose from.

While I allways had a leaning towards being told what was allocated and
then I could optimise my code to take advantage of any extra I got. In
the end it was just a waste of time. Having the allocator support a
realloc was usefull, after all it knew what the stratergy was and how
it was tracking things, so give it the ability to do the realloc.

But to be honest, giving them the size of the allocated block was
totally pointless.

I did provided a 'super fast' fixed size object allocator for use
within an individual process, and that proved really usefull. But it
was/is just a lib.

Chris

Chris Hinsley

unread,
Jun 16, 2011, 2:50:16 PM6/16/11
to

_if_ your allocator was really tuned for speed, and would give up a
large block to satisfy a small allocation request, then yes, it would
be usefull to be able to use the extra memory you got given. But if
your allocator is going to be abstract and can use whatever means it
wants, then it's a bit pointless.

But this is really getting very silly (oh dear I've used that word
again), in the end if your app is that sensative to the use of a little
bit of extra memory on the end of the block, then you should have just
allocated a little bit more to start with ? Or used a fixed size object
heap lib ? I mean how fast to you want to go ? Ultimate application
performance is not dependant on the underlying OS allocator !!!

Chris

Chris Hinsley

unread,
Jun 16, 2011, 3:12:29 PM6/16/11
to

And if I had a preference, I would want the OS allocator to take a
little extra time to get a good matched block, not too sloppy on
wasting memory, and leave it to me to use the bocks with my/a lib that
did hyper fast allocation for my specific need/s.

Chris

Albert van der Horst

unread,
Jun 16, 2011, 5:08:58 PM6/16/11
to
In article <2011Jun1...@mips.complang.tuwien.ac.at>,

Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
>Chris Hinsley <chris....@gmail.com> writes:
>>Having some under the hood way of finding the ammount allocated is just
>>asking for trouble. The allocator API either gives you the value or it
>>doesn't and you damb well stick to it !
>
>Yes, but what the original discussion was about (and what I am still
>discussing) is whether the API should be extended to provide this
>feature. While some others claim that it is totally useless, I think
>there are occasions where it is useful, and in principle ALLOCATED
>could be implemented at less cost than by tacking on a cell the way a
>library-level extension would.

I tried an implementation some time ago, and it can supply the
allocated size without extra effort.
I find it hard to imagine how RESIZE can be
implemented if the original size is not somehow available.

Not that I care much about having ALLOCATED available.
(Or for the MEMORY wordset at all, for that matter.)

>
>- anton

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

Chris Hinsley

unread,
Jun 16, 2011, 3:57:07 PM6/16/11
to
On 2011-06-16 22:08:58 +0100, Albert van der Horst said:

> In article <2011Jun1...@mips.complang.tuwien.ac.at>,
> Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
>> Chris Hinsley <chris....@gmail.com> writes:
>>> Having some under the hood way of finding the ammount allocated is just
>>> asking for trouble. The allocator API either gives you the value or it
>>> doesn't and you damb well stick to it !
>>
>> Yes, but what the original discussion was about (and what I am still
>> discussing) is whether the API should be extended to provide this
>> feature. While some others claim that it is totally useless, I think
>> there are occasions where it is useful, and in principle ALLOCATED
>> could be implemented at less cost than by tacking on a cell the way a
>> library-level extension would.
>
> I tried an implementation some time ago, and it can supply the
> allocated size without extra effort.
> I find it hard to imagine how RESIZE can be
> implemented if the original size is not somehow available.
>
> Not that I care much about having ALLOCATED available.
> (Or for the MEMORY wordset at all, for that matter.)
>
>>
>> - anton
>
> Groetjes Albert
>
> --

Yep, it's got to store it somewhere. But it's still a really fine point
to bother with returning it.

Either way, I agree with you, I don't give a monkeys if the OS gives me
the size of not.

Like I said before, either the OS provides the size as part of the API
contract or it dosn't. Either way it dosn't matter IMHO.

Chris

Paul Rubin

unread,
Jun 16, 2011, 7:54:48 PM6/16/11
to
an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
> I don't think that "untyped" has any place in a serious discussion.
> It just means that the person using that word does not know much about
> the language except that it deals with types in a way different from
> what the person prefers.

Chris Smith's excellent "What To Know Before Debating Type Systems"[1]
made the same distinction between strongly and weakly typed languages:

* Strong typing: A type system that I like and feel comfortable with

* Weak typing: A type system that worries me, or makes me feel
uncomfortable

Luca Cardelli's old article "Typeful Programming"[2] p. 52 says a bit
more about typelessness:

*Typeless programming.* Truly typeless languages include Assemblers,
BCPL and, to a minor extent, C; these languages regard raw memory as
the fundamental data structure. Large systems programmed in this
style become very hard to debug and maintain, hence we dismiss these
languages as obsolete, undisciplined, and unreliable. Although C
has a relatively rich notion of typing, the type enforcement is too
weak to lead predictably to robust systems.

*Type-free programming.* This concerns languages with some notion of
run-time typing (including strong typing) but no static typing
(Lisp, APL, Smalltalk). Unlike the previous category, large systems
built this way can be very easily debugged. ...

By that standard I would say that Forth is typeless. The usual argument
I've heard over the meaning of "untyped" revolves around whether Lisp is
typed (there is a tag in each runtime value saying what type it is) or
untyped (in the sense of untyped lambda calculus, i.e. not statically
typed). That's not what's at issue in vandys' post though.

[1] http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/
[2] http://www.lucacardelli.name/Papers/TypefulProg.pdf

Hugh Aguilar

unread,
Jun 16, 2011, 9:53:53 PM6/16/11
to
On Jun 15, 11:57 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
wrote:
> "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message

>
> news:a9913560-e64d-47e2...@c41g2000yqm.googlegroups.com...
>
>
>
> > You wouldn't be so confused if you were more cognizant of the
> > distinction between compile-time and run-time.
>
> I'm a C programmer.  I'm aware of both.  You're a Forth programmer.  You
> should be aware of neither, especially if you're an interpreted Forth
> programmer.  AIUI, even if you are a compiled Forth programmer, you
> still shouldn't need to concern yourself with this.  Compiled Forth should
> work the same as interpreted Forth.

You obviously have no idea what the difference is between compile-time
and run-time. Being a C programmer, you can't be aware of what compile-
time is, because C doesn't allow the programmer to write code that
executes at compile-time.

In Forth we can write code that executes at compile-time. This
includes IMMEDIATE words, the code prior to the DOES> in defining
words, all of the code in defining words such as I have in my novice
package (that use :NAME rather than CREATE DOES>), and so forth. This
has nothing at all to do with what kind of compilation scheme is being
used (direct-threaded, token-threaded, subroutine-threaded, etc.) ---
that is a completely different subject.

A thread like this isn't really the best place for learning about the
difference between compile-time and run-time. Read "Starting Forth" or
any other novice-Forth book for a discussion of the subject.

> > C's SIZEOF works at compile time because all of the variables have a
> > declared type. This includes both primitive types (int, float, etc.)
> > and user-defined struct types. SIZEOF can reckon their size at compile-
> > time, and this value is treated as a constant by the compiler.
>
> > By comparison, my ALLOCATION works at run-time.
>
> Why?
>
> I mean, C does what you're wanting to do and there is no need for this in C.
> So, why is there a need for this in Forth?

C doesn't do this at all! If you have a list in which the nodes can be
of various type nodes in it, C's typing system won't help you at all
--- you will have to declare VOID pointers, which completely defeats
the whole idea of typing. This is why C++ was invented --- so that you
could have a typed pointer to a struct (object), and the struct could
be of a parent type or of one of the child types derived from the
parent.

> Unfortunately, my answer depends on the answer to the following questions:
>   How are struct's implemented in Forth?
>   What binds the struct together as a unit?
>   What allows access to struct items?
>
> I suspect the answer is that a Forth word, probably using CREATE ... DOES> ,
> allocates the space for a struct and creates the named struct.  The named
> struct places it address on the stack, just like a Forth variable, when
> executed.  Then, other Forth words have hardcoded offsets used to access the
> struct items relative to the address for the struct in question.  If so,
> there should also be a Forth word that puts the size of the struct on the
> stack.  In which case, there is no need whatsoever for run-time
> functionality.

Look in my novice package for FIELD. It doesn't use CREATE DOES>, but
it functions effectively the same as the typical CREATE DOES>
implementations of FIELD. The use of FIELD is pretty common, although
I don't know of any literature that discusses it (not "Starting Forth"
or any other Forth Inc. publication that I'm aware of, to the best of
my recollection) --- maybe somebody else can recommend some literature
that discusses FIELD and structs and all of that good stuff.

> > This isn't going to work in the case of child data-types being
> > intermixed with parent data-types in a data structure.
>
> Don't do that.  That really is the solution.
>
> > You are only
> > considering the case in which one of the fields of the data-type is of
> > a variable size (typically a string), in which case you can solve the
> > problem by making the field a one-cell pointer and the data (the
> > string) an allocated memory-block elsewhere in the heap. I already do
> > that routinely, but that has little or nothing to do with the issue of
> > having different data-types in the same data structure.
>
> I think you need to learn about C's "union" keyword.

Don't do that??? That is the crux of programming!

I know C pretty well, although I haven't programmed in C for years (I
was a professional C programmer at one time). I know about unions. I
consider that to be a very clumsy mechanism. People use unions when
they don't have any kind of OOP facility at all --- but it is always
better to use child types when possible.

In my slide-rule program I used a union in my MARK data type:

list
w field .kind
\ the kind of mark this is (TNY, SML, MID, BIG or XTR)
f field .n
\ the numeric value of the mark (corresponds to .LABEL)
f field .dist
\ derived from N and measured in Lunits (distance from left edge)
w field .orientation
\ the direction of the label in relation to the mark
w field .label
\ the hstr of the label if there is a label
constant mark

I would have been much better off to make a MARK and LABEL type
distinct from each other (LABEL would be a child type of MARK). This
union of two data types is actually the ugliest code I've written in a
long time! I have one data type called MARK that is both a mark and a
label, and I have to test the .ORIENTATION field to determine which it
is. There is this embarrassing comment explaining the situation:
\ If .ORIENTATION is N/A, then there is no label and .LABEL is
irrelevant.
The reason why I did this, was because my novice package wasn't
complete at the time and I didn't have good support for doing it the
right way. This is just one of those many compromises that get made
when you have bad tools available. Given the current novice package
though, I wouldn't do it this way if I were writing the program now
--- I would be able to have child types, which is the right way to do
it.

What I find humorous is that I have to point out this sloppy code
myself! We have people such as Paul Rubin saying that my slide-rule
program is a lot of tedious work that most people wouldn't have
bothered with. He is resorting to troll-like meaningless criticism,
and he is failing to notice that there are perfectly good technical
criticisms that could be made. If people are going to criticize me,
they really could do a better job of noticing the actual problems in
my code --- why should I have to point out these problems myself?

The novice package is pretty powerful now --- it is a lot better than
it was at the time when I started writing the slide-rule program.

Even on my worst day as a Forth programmer though, I am still better
than C programmers on their best day, as they don't know what the
right way is --- at least when I do things wrong, I know that I'm
wrong (that is the first step toward doing things right).

Rod Pemberton

unread,
Jun 17, 2011, 1:46:45 AM6/17/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:efc98c67-12b2-45db...@j31g2000yqe.googlegroups.com...

>
> C doesn't do this at all! If you have a list in which the nodes can be
> of various type nodes in it, C's typing system won't help you at all
> --- you will have to declare VOID pointers, which completely defeats
> the whole idea of typing. This is why C++ was invented --- so that you
> could have a typed pointer to a struct (object), and the struct could
> be of a parent type or of one of the child types derived from the
> parent.
>

Wow, okay, I don't know where to begin. Apparently, there is much that is
wrong with your understanding of C. I'll mention the void pointers, but I'm
not going into the other issues.

Void pointers were added to C to prevent erroneous pointer dereferences.
Prior to that, all C pointers were typed, i.e., pointer-to-"something".
There was no pure pointer in C. Char pointers were used before void
pointers.

C++, for many, many years, was converted to C using a translator: Cfront.
So saying C++ was created to provide some additional functionality that C
itself didn't have is ludicrous. In fact, you used the same argument for
Forth200x and gForth being constrained by C. I.e., C++ must've been
constrained by C too.

> > I suspect the answer is that a Forth word, probably using CREATE ...
> > DOES> , allocates the space for a struct and creates the named struct.
> > The named struct places it address on the stack, just like a Forth
> > variable, when executed. Then, other Forth words have hardcoded
> > offsets used to access the struct items relative to the address for the
> > struct in question. If so, there should also be a Forth word that puts
> > the size of the struct on the stack. In which case, there is no need
> > whatsoever for run-time functionality.
>
> Look in my novice package for FIELD. It doesn't use CREATE DOES>, but
> it functions effectively the same as the typical CREATE DOES>
> implementations of FIELD. The use of FIELD is pretty common, although
> I don't know of any literature that discusses it (not "Starting Forth"
> or any other Forth Inc. publication that I'm aware of, to the best of
> my recollection) --- maybe somebody else can recommend some literature
> that discusses FIELD and structs and all of that good stuff.

Dude, I'm fully capable of learning about struct's in Forth. I suspect that
you may have missed the entire point of my comments.

> > Don't do that. That really is the solution.
> >

> Don't do that??? That is the crux of programming!
>

There are certain methods that work well. Other methods don't work so well
even if they are implementable. The point is you can choose to use methods
that are less complicated. I mentioned one such method, that should work
for Forth too. To me, it seems you're insisting on using a method which you
recognize is not working well or as well as you had hoped. However, you
refuse to change your ways, and try some other method. Instead, you insist
on complaining about your method not working.

(You can beat a tin can with a hammer and mostly flatten it, but you aren't
going beat it into a well formed dinner plate.)

> If people are going to criticize me,
> they really could do a better job of noticing the
> actual problems in my code --- why should I have
> to point out these problems myself?

You wrote it. For some unknown reason, you've assumed that others will,
want to, or should look at. No offense, but I've not looked at.

> ... they don't know what the right way is

The right way is to the right ... Do I get an A+?

BTW, what is the correct way, in your opinion?

> ... at least when I do things wrong, I know that
> I'm wrong ...

Then, why are you finding problems in your own code? Didn't you know you
were wrong right then when you were wrong? Apparently, you, like the rest
of us, only recognize the mistake after the fact ... The higher level human
mind only tracks so much stuff at once.


Rod Pemberton


Rod Pemberton

unread,
Jun 17, 2011, 1:52:56 AM6/17/11
to
"Rod Pemberton" <do_no...@noavailemail.cmm> wrote in message
news:iteppo$qkl$1...@speranza.aioe.org...

Correction:

> You wrote it. For some unknown reason, you've assumed that others will,
> want to, or should look at. No offense, but I've not looked at.
>

Where's the "at"? Somehow I forgot the two '"it's". That should've said:

want to, or should look at it. No offsense, but I've not looked at it.


Rod Pemberton


ken...@cix.compulink.co.uk

unread,
Jun 17, 2011, 4:28:30 AM6/17/11
to
In article <itb40j$m8i$1...@speranza.aioe.org>,
do_no...@noavailemail.cmm (Rod Pemberton) wrote:

> Most were designed by an academic or group: Pascal, Fortran, COBOL,
> PL/1, BASIC ...

I do not know about the others but Pascal and Basic have also changed
over time. There were and are lots of different implementations of Basic
and Object Pascal is a superset of standard Pascal and the latest
version of Delphi has a lot of stuff added compared with Delphi I.

Ken Young

Stephen Pelc

unread,
Jun 17, 2011, 7:02:33 AM6/17/11
to
On Thu, 16 Jun 2011 18:53:53 -0700 (PDT), Hugh Aguilar
<hughag...@yahoo.com> wrote:

>The use of FIELD is pretty common, although
>I don't know of any literature that discusses it (not "Starting Forth"
>or any other Forth Inc. publication that I'm aware of, to the best of
>my recollection) --- maybe somebody else can recommend some literature
>that discusses FIELD and structs and all of that good stuff.

See chapters 8 and 11 of "Programming Forth" by Stephen Pelc.
http://www.mpeforth.com/books.htm

Stephen


--
Stephen Pelc, steph...@mpeforth.com
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeforth.com - free VFX Forth downloads

Hugh Aguilar

unread,
Jun 18, 2011, 9:18:02 AM6/18/11
to
On Jun 16, 11:46 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>

wrote:
> "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message
> BTW, what is the correct way, in your opinion?
>
> > ... at least when I do things wrong, I know that
> > I'm wrong ...
>
> Then, why are you finding problems in your own code?  Didn't you know you
> were wrong right then when you were wrong?  Apparently, you, like the rest
> of us, only recognize the mistake after the fact ...  The higher level human
> mind only tracks so much stuff at once.

That slide-rule program provided pretty much a textbook example of the
need for inheritance. The scales are lists of marks. About 5-10% of
the marks have labels attached to them. The correct way to implement
this, would be with a MARK data-type that describes the mark, and a
LABELED-MARK data-type that is a child of the MARK data-type --- it is
a mark, but with the extra fields needed to additionally describe the
attached label (the .ORIENTATION and .LABEL fields).

The reason why I didn't do this, and used a union instead, was because
at that time I didn't have a CLONE-LIST function that could clone a
list containing nodes of different types (MARK and LABELED-MARK in
this case). The reason why CLONE-LIST couldn't do this, was because it
had no way of determining the size of each node (which it needs to
give to CMOVE> internally). Later on I rewrote the heap-memory words
so that they would include an ALLOCATION function, and I also rewrote
CLONE-LIST to use ALLOCATION to determine the size of each node. By
that time however, the slide-rule program already used the hack
involving the union written, so I didn't bother to go back and rewrite
all of that code (it is a pretty big program, after all).

It is not that I recognized the mistake after the fact --- I was well
aware of ANS-Forth's lack of an ALLOCATION function --- it just takes
time for me to fix all of the problems in ANS-Forth. Writing
applications in ANS-Forth is a major hassle because right in the
middle of the job, I run into some gaping omission in ANS-Forth, and I
have to either work around it (such as by using a union when I should
have used inheritance), or I have to interrupt my application-writing
to fix the design problem in ANS-Forth. The whole point of making
ALLOCATION part of the standard, is so that application programmers in
the future don't run into the same problem over and over again.

ANS-Forth is actually a terrible language for writing applications.
That slide-rule program would have been much easier to write in any of
the myriad languages available that support OOP. The only language
that would have been worse than ANS-Forth, would have been C. For
almost any large application though, you need to have at least a
modicum of support for OOP --- this fact has been well known since the
late 1980s when the OOP revolution transformed programming ---
although the ANS-Forth committee seems to have been pretty oblivious
to this fact in 1994 when they released the ANS-Forth standard (and
now, in 2011, they are still just as oblivious as they were in 1994).

Hugh Aguilar

unread,
Jun 18, 2011, 11:28:39 AM6/18/11
to
On Jun 17, 5:02 am, stephen...@mpeforth.com (Stephen Pelc) wrote:
> On Thu, 16 Jun 2011 18:53:53 -0700 (PDT), Hugh Aguilar
>
> <hughaguila...@yahoo.com> wrote:
> >The use of FIELD is pretty common, although
> >I don't know of any literature that discusses it (not "Starting Forth"
> >or any other Forth Inc. publication that I'm aware of, to the best of
> >my recollection) --- maybe somebody else can recommend some literature
> >that discusses FIELD and structs and all of that good stuff.
>
> See chapters 8 and 11 of "Programming Forth" by Stephen Pelc.
>  http://www.mpeforth.com/books.htm

Well, I downloaded your book and I found this definition:

: field \ offset n <"name"> -- offet’ ; Exec: addr -- 'addr
\ Create a new field within a structure definition of
\ size n bytes.
create immediate \ the child is IMMEDIATE
over , +
does>
@ state @ if \ compile
postpone literal postpone +
else
+
then
;

That is a pretty good definition of FIELD --- you didn't write it
though --- that code was written by David Williams:
http://groups.google.com/group/comp.lang.forth/browse_thread/thread/d90c532cae6410f7

Then you go on to give us these useless words:

: struct \ -- addr 0 ; -- size
\ Begin definition of a new structure. Use in the form
\ STRUCT <name>
\ At run time <name> returns the size of the structure.
create
here 0 , 0 \ mark stack, lay initial offset
does>
@ \ get size of structure
;

: end-struct \ addr n --
\ Terminate definition of a structure.
swap ! \ set size of structure
;

You are completely failing to support inheritance! In my novice
package, I allow one struct to be derived from another struct. For
example, here is a struct:

0
w field .fore
constant list

And here is a child struct that inherits all of the fields in the LIST
struct, but adds some more:

list
w field .line
constant seq

I didn't bother to read any further in your book than the discussion
of structs in chapters 8 and 11 that you referenced in your post. I
wouldn't recommend the book to people learning Forth however. You are
using other people's code without giving them credit. You are also
failing to understand rudimentary programming concepts, such as
inheritance. Your book is both original and good --- unfortunately,
the part that is original isn't good, and the part that is good isn't
original.

Message has been deleted

David N. Williams

unread,
Jun 18, 2011, 1:49:56 PM6/18/11
to
On 6/18/11 11:28 AM, Hugh Aguilar wrote:
> On Jun 17, 5:02 am, stephen...@mpeforth.com (Stephen Pelc) wrote:
>> [...]

>>
>> See chapters 8 and 11 of "Programming Forth" by Stephen Pelc.
>> http://www.mpeforth.com/books.htm
>
> Well, I downloaded your book and I found this definition:
>
> : field \ offset n<"name"> -- offet� ; Exec: addr -- 'addr

> \ Create a new field within a structure definition of
> \ size n bytes.
> create immediate \ the child is IMMEDIATE
> over , +
> does>
> @ state @ if \ compile
> postpone literal postpone +
> else
> +
> then
> ;
>
> That is a pretty good definition of FIELD --- you didn't write it
> though --- that code was written by David Williams:
>
http://groups.google.com/group/comp.lang.forth/browse_thread/thread/d90c532cae6410f7

Wow! When I wrote that very similar (not identical) version in
2010, I was unaware of the code in "Programming Forth". But I
did find a copy of that book copyrighted 2005 on my computer,
which already has it. So it wasn't original with me.

The caveats about state smartness were already there, too.
Because of discussion in c.l.f., maybe in the thread you quoted,
I removed the state-smart version from my plainstruct.fs utility
in July, 2010, in favor of an explicit early binding option.

-- David

Rod Pemberton

unread,
Jun 19, 2011, 1:17:17 AM6/19/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:c6e714c7-d954-4ca0...@36g2000yqj.googlegroups.com...

> On Jun 16, 11:46 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
> wrote:
> > "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message
>
> > > ... at least when I do things wrong, I know that
> > > I'm wrong ...
> > [snip]
>
> That slide-rule program

Wow, what a conversation *killer* ...

> need for inheritance.

Sigh ...

C programmer. AFAIK, no need for inheritance. There is nothing I'm aware
of that C++ can do that C cannot.

> The reason why I didn't do this, and used a union instead, was because
> at that time I didn't have a CLONE-LIST function that could clone a
> list containing nodes of different types (MARK and LABELED-MARK in
> this case).

Can you explain to me why a memory copy cannot copy the entire list of
nodes? I.e., not contiguous memory ...

> The reason why CLONE-LIST couldn't do this, was because it
> had no way of determining the size of each node (which it needs to
> give to CMOVE> internally).

Is the entire list allocated in contiguous memory space? If not, can you
compact it so that it is in contiguous memory space, and then copy it
all-at-once?

> Later on I rewrote the heap-memory words
> so that they would include an ALLOCATION function, and I also rewrote
> CLONE-LIST to use ALLOCATION to determine the size of each node.

You are aware that Forth itself implements it's dictionary with a
linked-list with variable sized nodes without any apparent ALLOCATION or
SIZEOF word or function, yes? What's the problem?

> [...] I run into some gaping omission in ANS-Forth [...]

I'm not able to rank your abilities with Forth since mine are so minimal.
My guess is that it's a disconnect between "The ANS Forth way" and "your
way".

> [...] have to either work around it (such as by using a union when


> I should have used inheritance)

My personal experiences with *having* to work around something, usually
means there was an easier way that was a better fit to the language that I
missed: wrong frame of mind, ignorant of some function, etc.

> That slide-rule program would have been much easier to write in any of
> the myriad languages available that support OOP. The only language
> that would have been worse than ANS-Forth, would have been C.

Sigh ... Now, I think you seriously missed something or multiple things of
importance in your C experiences.

> For almost any large application though, you need to have at
> least a modicum of support for OOP --- this fact has been well
> known since the late 1980s when the OOP revolution transformed
> programming ---

So, the 5 MLOC RT OLTP database written in PL/1 variant, a non-OOP language,
that I programmed on for a few years after 2000 must've had "hidden" OOP
functionality? Laughter ... Wow, I guessed I just totally missed that!

You do *not need* OOP to code extremely large applications. You may *want*
OOP for other reasons, e.g., reduces cut-n-paste errors. It's far from a
fact that OOP is needed for anything.

> [OOP revolution] although the ANS-Forth committee seems to


> have been pretty oblivious to this fact in 1994 when they released
> the ANS-Forth standard (and now, in 2011, they are still just as
> oblivious as they were in 1994).

Why do you say that? My understanding is OOP-like functionality in forth is
characterized by the code and data "templates" created by using CREATE (or
<BUILDS) and DOES> . AFAIK, ANS has CREATE and DOES> .


Rod Pemberton


Stephen Pelc

unread,
Jun 19, 2011, 4:58:22 AM6/19/11
to
On Sat, 18 Jun 2011 08:28:39 -0700 (PDT), Hugh Aguilar
<hughag...@yahoo.com> wrote:

>That is a pretty good definition of FIELD --- you didn't write it
>though --- that code was written by David Williams:

>http://groups.google.com/group/comp.lang.forth/browse_thread/thread/d90c532=
>cae6410f7

See David Williams response.

>You are completely failing to support inheritance!

Rubbish! In the sense that you mean it, try:

struct point
cell field pt.x
cell field pt.y
end-struct

struct line
point field line.start
point field line.end
end-struct

As you claim, you appear not to read other people's works.

BruceMcF

unread,
Jun 19, 2011, 9:27:31 PM6/19/11
to
On Jun 19, 1:17 am, "Rod Pemberton" <do_not_h...@noavailemail.cmm>

wrote:
> "Hugh Aguilar" <hughaguila...@yahoo.com> wrote in message
> > [OOP revolution] although the ANS-Forth committee seems to
> > have been pretty oblivious to this fact in 1994 when they released
> > the ANS-Forth standard (and now, in 2011, they are still just as
> > oblivious as they were in 1994).

> Why do you say that?  My understanding is OOP-like functionality
> in forth is characterized by the code and data "templates" created
> by using CREATE (or <BUILDS) and DOES> .  AFAIK, ANS has CREATE
> and DOES> .

Indeed, there are several OOP libraries available in standard Forth94,
with a range of OOP approaches supported.

Hugh Aguilar

unread,
Jun 20, 2011, 1:01:33 AM6/20/11
to
On Jun 19, 2:58 am, stephen...@mpeforth.com (Stephen Pelc) wrote:
> On Sat, 18 Jun 2011 08:28:39 -0700 (PDT), Hugh Aguilar
> >You are completely failing to support inheritance!
>
> Rubbish! In the sense that you mean it, try:
>
> struct point
>   cell field pt.x
>   cell field pt.y
> end-struct
>
> struct line
>   point field line.start
>   point field line.end
> end-struct
>
> As you claim, you appear not to read other people's works.

You don't know what inheritance is! It is certainly possible to have a
struct that contains fields that are other structs (as in your code
above) or are pointers to other structs (see my DECOMMA struct in the
list package), but this is not inheritance.

The idea of inheritance, is that a child struct is built on top of the
parent struct. The child struct has all of the fields of the parent
struct, with its own field appended on top of them. In my example,
LIST was the parent struct and SEQ was the child struct. The idea
here, is that all of the functions that work with the parent struct
will also work with the child struct, because the fields that they
expect to find in the record are in fact there. In my example, all of
the functions that work with the LIST struct will work with the SEQ
struct.

It is possible for a programmer to define a child struct without
knowing what fields are in the parent struct. This is called
"information hiding." For example, you don't have to know about
the .FORE field in the LIST struct. You could define the SEQ struct as
I did, and you could use all of the list functions (such as EACH,
etc.) on your SEQ lists, and you wouldn't have to know anything about
the internal machinations of these functions or about the fields in
the LIST struct. I could redefine my LIST to be an array (similar to
Factor's sequences), and also redefine all of the associated functions
(EACH, etc.) to work with arrays rather than lists, and your code
would compile and run just fine --- because none of your code
explicitly accesses the LIST fields (such as .FORE) --- because you
aren't using any "carnal knowledge" of the internal machinations of
the LIST functions.

Your STRUCT and END-STRUCT functions *force* every struct to have an
initial size of zero. Each struct then only contains its own fields,
and there is no parent struct whose fields get automatically included
in the struct. I can really discern no purpose at all for STRUCT and
END-STRUCT except to *prevent* inheritance. You don't know what
inheritance is though, so most likely your purpose in writing STRUCT
and END-STRUCT was just to prettify the source-code in the sense that
CONSTANT no longer had to be used explicitly.

It is really depressing for me to have to explain a rudimentary
programming concept such as inheritance to a member of the Forth-200x
committee. Concepts such as this are well known even among teenagers
--- OOP became popular in the late 1980s, although the concepts have
been known as far back as the 1960s --- OOP just formalized these
concepts in the sense that we were given a vocabulary for talking
about what we were already doing (words like "inheritance,"
"polymorphism," etc.). It just blows my mind that I have to explain
something like inheritance to you in the year 2011.

This reminds me that you are the same guy who stated that a cross-
compiler needs to simulate the target processor on the host processor
at compile-time. What an ignoramus you are! I really don't think that
there is any hope for Forth-200x --- being a Forth programmer is like
riding on the short bus --- you guys don't know anything about
computer science.

Rod Pemberton

unread,
Jun 20, 2011, 3:29:24 AM6/20/11
to
"Hugh Aguilar" <hughag...@yahoo.com> wrote in message
news:62eb9e06-c24c-4d0f...@i4g2000yqg.googlegroups.com...

>
> It is possible for a programmer to define a child struct without
> knowing what fields are in the parent struct.
>

What's the point of that? That seems pretty stupid to me. If you don't
know what they are you cannot access them. If you cannot access them, you
cannot use them. You can do nothing with it. I.e., you have no need of the
parent struct. What purpose does it serve?

Why bother with making a struct a child struct if you have no need of the
parent struct? One would think that the child struct isn't really a child
struct at all, but a non-related struct if it inherits nothing of value from
its parent struct ... What's the point of assigning the child to a parent
which is useless to the child?

> This is called "information hiding."

If the struct wasn't a child struct, then not being able to access the
information in the now passed-over-as-parent struct is still called
"information hiding." Either way, you've got no access to the parent's
information: information hidden. I don't see any difference. What's the
point of being a child struct?

> For example, you don't have to know about
> the .FORE field in the LIST struct.

If you didn't make the struct a child struct in the first place, you
definately won't ...

> [...] you wouldn't have to know anything about


> the internal machinations of these functions or about the
> fields in the LIST struct.

If someone else wrote linked-list package and you used it, then you


"wouldn't have to know anything about the internal machinations of these

functions or about the fields in the LIST struct" either. Problem solved?


Rod Pemberton

Alex McDonald

unread,
Jun 20, 2011, 5:10:03 AM6/20/11
to

I've had enough of you and your ad-homs. I've banned you from the
Win32Forth Yahoo group.

Stephen Pelc

unread,
Jun 20, 2011, 6:08:33 AM6/20/11
to
On Sun, 19 Jun 2011 22:01:33 -0700 (PDT), Hugh Aguilar
<hughag...@yahoo.com> wrote:

>The idea of inheritance, is that a child struct is built on top of the
>parent struct. The child struct has all of the fields of the parent
>struct, with its own field appended on top of them.

Your idea of inheritance can be expressed as

struct HAline
point +
point TreatedDifferentlyPoint
end-struct

or even (and I have seen it used)
struct MyStruct
xxx -
...
end-struct

>Your STRUCT and END-STRUCT functions *force* every struct to have an
>initial size of zero.

Not forces but defaults.

Your problem with STRUCT ... END-STUCT and friends is that you cannot
see the possibilities of handling a default offset on the stack. Once
you understand that that you can add and subtract to this offset, the
usage will become clearer.

Hugh Aguilar

unread,
Jun 20, 2011, 10:23:59 PM6/20/11
to
On Jun 20, 4:08 am, stephen...@mpeforth.com (Stephen Pelc) wrote:
> On Sun, 19 Jun 2011 22:01:33 -0700 (PDT), Hugh Aguilar
>
> <hughaguila...@yahoo.com> wrote:
> >The idea of inheritance, is that a child struct is built on top of the
> >parent struct. The child struct has all of the fields of the parent
> >struct, with its own field appended on top of them.
>
> Your idea of inheritance can be expressed as

That isn't my idea of inheritance, that is everybody's idea --- as I
said, the concept has been well known for many decades.

> struct HAline
>   point +
>   point TreatedDifferentlyPoint
> end-struct

I think what you are aiming for is:

struct HAline
point +
point field TreatedDifferentlyPoint
end-struct

That works, but it is just ugly --- you are setting the initial size
incorrectly, and then fixing it afterward.

In most applications, the vast majority of structs are going to be
child structs. You typically have a few data-structure structs (such
as my LIST) in a library and a lot of child structs in the application
each using one of those as their parent. It is pretty rare for a
struct to be defined that isn't part of a data structure of some kind
(the only reason to do this is to decrease stack clutter by putting
related data inside of a struct and passing a pointer to the struct
around on the stack).

I really don't see any purpose to your STRUCT and END-STRUCT
functions. These functions are just a lot of rigamarole whose only
purpose is to set the initial size to a value that is almost always
incorrect.

> or even (and I have seen it used)
> struct MyStruct
>   xxx -
>   ...
> end-struct

This makes no sense at all --- I can't think of any reason why you
would want to subtract from the initial size. Where have you seen this
used? Did the program work?

What you said in your previous post was that "inheritance" is
accomplished by putting struct fields inside of a struct. That is
definitely not true --- that is why I said that you didn't know what
inheritance is. Now you say that it is possible to use the size of a
parent struct as the initial size of a child struct, which is
essentially inheritance. This is something that really could have been
discussed in your book --- all you did was give the reader STRUCT and
END-STRUCT, whose sole purpose is to set the initial size to a value
that is almost never correct, and not explain to the reader that it is
possible to manually fix the problem and that this is something that
he needs to do every time --- most readers are going to go away with
the idea that inheritance is being disallowed for some obscure reason.
I'll give you the benefit of the doubt though, and assume that you do
know what inheritance is --- I apologize for saying that you are
*that* big of an idiot.

I still think that simulating the target processor at compile-time in
a cross-compiler is idiocy though --- it just blows my mind that you
don't know how to write a cross-compiler, considering that cross-
compilers are your business and have been for many years. I figured
out how to write a cross-compiler when I worked at Testra. I was
pretty baffled as to how to do this, but I went for long bicycle rides
to think on the subject, and then suddenly while riding the answer
came to me --- have you tried doing that yet?

Hugh Aguilar

unread,
Jun 21, 2011, 1:49:16 AM6/21/11
to
On Jun 16, 7:45 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:

> Chris Hinsley <chris.hins...@gmail.com> writes:
> >Having some under the hood way of finding the ammount allocated is just
> >asking for trouble. The allocator API either gives you the value or it
> >doesn't and you damb well stick to it !
>
> Yes, but what the original discussion was about (and what I am still
> discussing) is whether the API should be extended to provide this
> feature.  While some others claim that it is totally useless, I think
> there are occasions where it is useful, and in principle ALLOCATED
> could be implemented at less cost than by tacking on a cell the way a
> library-level extension would.

Actually, the discussion was concluded a long time ago:

From: Leon Wagner <le...@forth.com>
To: fort...@yahoogroups.com
Sent: Mon, February 1, 2010 9:00:11 PM
Subject: RE: [forth200x] ALLOCATED (formerly SIZE) RfD

I don't support this feature and would likely not implement it. Other
than the nice discussion of what to name it, I
see no compelling reason for its actual use.

---------

If Forth Inc. is not going to support ALLOCATED, then ALLOCATED is not
going to become part of the Forth-200x standard. You can *discuss* the
technical merits all that you want, but Leon Wagner has made his
decision --- you don't have the authority to buck Leon Wagner, any
more than I do. The job of a teacher is to support the industry
standard, which in this case means preparing students to apply for
work at Forth Inc..

Forth Inc. has an OOP package that comes with SwiftForth. All of their
own legacy code involving OOP style programming was written using that
OOP package. They have no interest in supporting ALLOCATED, which is
essentially my effort to introduce rudimentary OOP capability into
standard Forth. I can do without polymorphism, which is difficult to
implement, but something like ALLOCATED is pretty much required for
OOP style programming, and it is simple to implement --- hence the
RfD. I was just thinking of myself though; I wasn't really trying to
boost SwiftForth sales, so there was no reason for Leon Wagner to
support my RfD. For him, Forth is how he makes his living; he isn't
going to listen to hobbyists. I don't blame him for keeping his eye on
the money --- I am pretty focused on making money when I am driving my
taxicab, and I don't help people out with their many many problems
which they tell me about.

I have already said that I am going to introduce a competing Forth
standard, which I call Straight Forth. If you want to have discussions
in which your opinion carries some weight, you can join me in that
endeavor. I'm not like Leon Wagner --- I won't just cut off a
discussion by fiat --- I will listen to people's opinions, so long as
they are focusing on technical matters. It is all just for fun anyway,
so there is no reason to quash any reasonable idea.

When I say that I will listen to people who are focusing on technical
matters, I mean that I am willing to listen to discussions of what
*can* be done. I don't really want to listen to people telling me that
they can't succeed at something:

On Jun 15, 3:52 am, Alex McDonald <b...@rivadpm.com> wrote:
> Many systems (Linux, BSD, every version of IBM mainframe systems to z/
> OS and others) do not provide any mechanism for discovering this
> length information. Here are the standard Linux kernel calls;
>
> void *kmalloc( size_t size, int flags );
> void kfree( const void *objp );
>
> There isn't any way of getting what you want from the system.

Alex McDonald

unread,
Jun 21, 2011, 4:33:11 AM6/21/11
to

begin-structure voc%
6 cells -
field: voc.thrd
field: voc.head
field: voc.srch
field: voc.iter
field: voc.xt
field: voc.link
field: voc.#0
5 cells +
end-structure

It's a header in front of a wordlist that makes it a vocabulary.


>
> What you said in your previous post was that "inheritance" is
> accomplished by putting struct fields inside of a struct. That is
> definitely not true --- that is why I said that you didn't know what
> inheritance is. Now you say that it is possible to use the size of a
> parent struct as the initial size of a child struct, which is
> essentially inheritance. This is something that really could have been
> discussed in your book --- all you did was give the reader STRUCT and
> END-STRUCT, whose sole purpose is to set the initial size to a value
> that is almost never correct, and not explain to the reader that it is
> possible to manually fix the problem and that this is something that
> he needs to do every time --- most readers are going to go away with
> the idea that inheritance is being disallowed for some obscure reason.
> I'll give you the benefit of the doubt though, and assume that you do
> know what inheritance is --- I apologize for saying that you are
> *that* big of an idiot.
>
> I still think that simulating the target processor at compile-time in
> a cross-compiler is idiocy though --- it just blows my mind that you
> don't know how to write a cross-compiler, considering that cross-
> compilers are your business and have been for many years. I figured
> out how to write a cross-compiler when I worked at Testra. I was
> pretty baffled as to how to do this, but I went for long bicycle rides
> to think on the subject, and then suddenly while riding the answer
> came to me --- have you tried doing that yet?

Hugh, you're all mouth and trousers.

BruceMcF

unread,
Jun 21, 2011, 11:58:20 AM6/21/11
to
On Jun 21, 4:33 am, Alex McDonald <b...@rivadpm.com> wrote:
> begin-structure voc%
>  6 cells -
>   field:  voc.thrd
>   field:  voc.head
>   field:  voc.srch
>   field:  voc.iter
>   field:  voc.xt
>   field:  voc.link
>   field:  voc.#0
>  5 cells +
> end-structure

> It's a header in front of a wordlist that makes it a vocabulary.

I believe that what Hugh is looking for is not ``5 cells +'' but
rather a specific ``inherit:'' ~ which is to say, the syntactic sugar
for the above ...

> begin-structure voc%
> 6 cells -
> field: voc.thrd
> field: voc.head
> field: voc.srch
> field: voc.iter
> field: voc.xt
> field: voc.link

inherit: ...

> field: voc.#0
> 5 cells +
> end-structure

Though given Hugh's approach to array dimensions, surely it would be
appropriate to have a different ``inherit:'' operator for each
possible different size of structure, ``inherit1char:'',
``inherit2chars:'', ``inherit1cell:'', ``inherit2cells:'', and etc.

John Passaniti

unread,
Jun 21, 2011, 11:59:21 AM6/21/11
to
On Jun 20, 1:01 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> The idea of inheritance, is that a child struct is built
> on top of the parent struct. [...]

Yes, this is the idea of a particular form of inheritance. In
particular, it is a common idea in class-based inheritance and
(unfortunately) there are plenty of people who equate OOP with classes
(and classes with fixed-form structures in memory). But there are
other forms of inheritance that don't involve classes at all.
Prototype-based languages (like Self, JavaScript, and the usual use of
Lua) avoid classes entirely and instead rely on a more flexible and
dynamic notion of objects. And in fact, I think that most of the
historical antagonism against OOP in the comp.lang.forth community is
in part due to class-based notions. Classically, the problem most
people have with class-based notions of OOP is that they require
modeling the system in terms of strict taxonomies, and some people
have a hard time mapping classes and sub-classes on real-world
objects. You obviously can do it, but it sometimes becomes clumsy.
Prototype-based OOP (and more flexible notions of inheritance it has)
dispense with classes and instead let you build up objects in terms of
exactly the behavior and data you need.

Hugh Aguilar

unread,
Jun 21, 2011, 8:09:03 PM6/21/11
to

I still don't see any purpose in having negative offsets for fields,
and the record address in the middle of the record.

I think what you are trying to do, is to have the offsets for all the
fields to the main record (the positive offsets) remain the same, no
matter how big the inherited record prepended on it may be. That makes
no sense to me though! Why would you want to do that?

Why not just have the child struct inherit the parent struct the way
that I described. If the parent struct has changed somehow, then just
recompile the application. For example, lets say that I rewrote my
LIST struct so that it was a doubly-linked list rather than a singly-
linked list, and I rewrote all of the list functions so that they
continued to do the exact same thing as before but with double links
rather than single links (I may do this in the next novice package
upgrade). In this case, LIST is no longer going to be a single cell in
size, but is going to be two cells in size. Just recompile your
application and you are good to go. You don't have to change your
source-code at all, as LIST is still called LIST and all of the
functions still have the same names and do the same things. You are
going to have to recompile your application anyway, because the
functions are at different addresses what with the list package having
been recompiled, so the size of LIST having changed isn't the only
reason why you have to recompile.

I just don't get any of this weirdness involving records with
negatively offset fields --- I think you are making something simple
into something hugely complicated, for no purpose at all. I mean, come
on, we are talking about structs --- this is kindergarten programming
--- where does all of this complexity come from? I'm not looking for
any syntactic sugar for something that makes no sense in any form ---
I prefer to just use simple straightforward programming --- like I did
in LIST.4TH and ASSOCIATION.4TH.

Alex McDonald

unread,
Jun 22, 2011, 6:13:51 AM6/22/11
to

Win32Forth builds vocabularies on top of wordlists. In fact, wordlists
are really vocabularies. This technique allows the structure to be
either processed as a wordlist (from offset 0) or a vocabulary (same
offset of 0, vocabulary stuff at negative offsets).

Voila. The "thing" at offset 0 can be both a wordlist and a
vocabulary. Words that deal with wordlists only or vocabularies only
or even both simultaneously do not need to be specific as to which
they are operating on; everything "wordlistish" is at the *same +ve
offset in both.

>
> Why not just have the child struct inherit the parent struct the way
> that I described. If the parent struct has changed somehow, then just
> recompile the application. For example, lets say that I rewrote my
> LIST struct so that it was a doubly-linked list rather than a singly-
> linked list, and I rewrote all of the list functions so that they
> continued to do the exact same thing as before but with double links
> rather than single links (I may do this in the next novice package
> upgrade). In this case, LIST is no longer going to be a single cell in
> size, but is going to be two cells in size. Just recompile your
> application and you are good to go. You don't have to change your
> source-code at all, as LIST is still called LIST and all of the
> functions still have the same names and do the same things. You are
> going to have to recompile your application anyway, because the
> functions are at different addresses what with the list package having
> been recompiled, so the size of LIST having changed isn't the only
> reason why you have to recompile.
>
> I just don't get any of this weirdness involving records with
> negatively offset fields --- I think you are making something simple
> into something hugely complicated, for no purpose at all. I mean, come
> on, we are talking about structs --- this is kindergarten programming
> --- where does all of this complexity come from? I'm not looking for
> any syntactic sugar for something that makes no sense in any form ---
> I prefer to just use simple straightforward programming --- like I did
> in LIST.4TH and ASSOCIATION.4TH.

What's complicated or weird about it? I get to change the vocabulary
structure and don't need to rewrite a single piece of code (or even
recompile it for binaries). All I do is simply add more stuff at
larger negative offsets. There is no difference in the source code
that uses structures with 0 to +ve offsets as compared with -ve to +ve
offsets. None.

You claim to have been a mainframe programmer. Go look at the DSECTs
IBM provide for system structures, like the TCB or ASCB. Yards of
negative offset fields, for exactly the same reasons; one, it makes no
difference to the programmer, and two, it allows structures like the
ASCB become an ASXB by extending "south". No recompiling, no change to
source code, no hassle.

I think you're claiming it's complicated because you launched into
your usual "I'm an expert, you're an idiot on the short bus" spiel and
it's suddenly dawned on you that you've been parading around with your
shorts round your ankles.

David Thompson

unread,
Jun 27, 2011, 3:06:13 AM6/27/11
to
On Wed, 15 Jun 2011 16:16:33 -0400, "Rod Pemberton"
<do_no...@noavailemail.cmm> wrote:
<snip>
> C has lots of "warts" too. That's because the language was used in real
> world systems and extended and changed over time. Forth was too. Most

Concur.

> aren't. Most were designed by an academic or group: Pascal, Fortran, COBOL,
> PL/1, BASIC ...
>
Original FORTRAN and COBOL were entirely industry/user and
largely scorned by academia*, and have evolved at least as much
(admittely over a longer time). Fortran >= 90, which coincides
with and is sometimes indicated by the mixed-case spelling, is
pulled some by theory, but not very much. (* Scorned as language
designs, that is; fields needing numerics, like physics and
engineering, accepted FORTRAN as a tool.)

BASIC and Pascal were designed as pedagogical, but both enjoyed(?)
plenty of practical use and (resulting) evolution. Both were common on
the varied micros that preceded the IBM PC, all now effectively gone,
and Pascal on the early Apple Macintosh.

Ada was formally designed and held to it (mostly) but never gained
much traction, especially after (US)DoD stopped pushing it. AFAICS
Java and maybe Python is(are) the only consciously-designed
general-purpose language(s) getting serious use now.

Doug Hoffman

unread,
Jul 11, 2011, 10:08:37 AM7/11/11
to
On 6/21/11 11:59 AM, John Passaniti wrote:
> On Jun 20, 1:01 am, Hugh Aguilar<hughaguila...@yahoo.com> wrote:
>> The idea of inheritance, is that a child struct is built
>> on top of the parent struct. [...]
>
> Yes, this is the idea of a particular form of inheritance. In
> particular, it is a common idea in class-based inheritance and
> (unfortunately) there are plenty of people who equate OOP with classes
> (and classes with fixed-form structures in memory). But there are
> other forms of inheritance that don't involve classes at all.
> Prototype-based languages (like Self, JavaScript, and the usual use of
> Lua) avoid classes entirely and instead rely on a more flexible and
> dynamic notion of objects. And in fact, I think that most of the
> historical antagonism against OOP in the comp.lang.forth community is
> in part due to class-based notions.

Sorry for the late reply.

My recollection is the issues went more or less like this:

1) Forth already has all the OOP anyone needs built-in with
create/does>. Or not.
2) The syntax should be (message-object or object-message). Pick your
favorite.
3) All message sends should be late bound. Or message sends can be
early bound if the compiler knows the type of object. And/or specific
message sends can be forced to early bind by the programmer. Pick a
combination.
4) An object's data should only be accessed via messages. Or not. Take
your pick. Of course if you go the methodless access route then that
treads on the only-late-bound messages concept in 3).
5) Messages should be global in scope. Or messages should only be in
scope as set by a preceding object. Take your pick.
6) Speed is important (high priority). Or not. Take your pick.
7+) I'm sure there were more, but I think I got most of them.

Not sure if any of the debated issues involved class-based vs
prototype-based approaches or the inheritance scheme.

-Doug

Hugh Aguilar

unread,
Jul 14, 2011, 1:22:38 AM7/14/11
to

I don't think that a full-blown OOP system is appropriate for micro-
controllers. On the other hand, you do sometimes have data structures
that contain nodes of different types. With my ALLOCATION, I'm just
supporting a simple system that allows for inheritance, without
attempting a full-blown OOP.

The same thing is true of :NAME --- I am just supporting a simple
system for associating more than one action to each datum --- I am not
attempting a full-blown OOP with messages being sent to the DOES> code
as strings.

Everything in my novice package is simple. I don't try for big
complicated solutions --- I like simplicity --- but CREATE DOES> is
*too* simple.

Julian Fondren

unread,
Jul 14, 2011, 5:38:00 AM7/14/11
to
On Jul 14, 12:22 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> The same thing is true of :NAME --- I am just supporting a simple
> system for associating more than one action to each datum --- I am not
> attempting a full-blown OOP with messages being sent to the DOES> code
> as strings.
>
> Everything in my novice package is simple.

16 constant cstr-levels \ how many CSTR> buffers there
are; how many nesting levels allowed for <CSTR
... roughly 150 lines later ...
cr ." You did not enter a valid Yea or Nay. Try again: "
repeat ;

: :name ( str wid -- )
get-current >r set-current
<cstr
c" : " +cstr +cstr c" " +cstr
cstr> count evaluate
r> set-current ;

With special honor to

: y/n? ( adr cnt -- y/n? true | false ) \ top flag indicates if
string is a valid Yay or Nay
-leading \ --
adr cnt
0= if drop false exit then \ --
adr
c@ \ --
char
dup [char] Y = if drop true true exit then
dup [char] y = if drop true true exit then
dup [char] N = if drop false true exit then
dup [char] n = if drop false true exit then
drop false ;

I'm not replying just to mock you -- I'm actually sympathetic to your
irritation with people who don't show code -- but come on, it wasn't
simplicity that drove all that <cstr stuff. You don't have ;, swap,
lit*, for simplicity. You don't yet have five separate array-lookup
syntaxes, but you've expressed interest in more than two :-)

: -leading ( c-addr u -- c-addr' u' )
begin dup while over c@ bl <> ?exit 1 /string repeat ;

: y/n? ( c-addr u -- f -1 | 0 )
-leading if c@ bl or dup
[char] y = swap [char] n = over or if true then exit
then drop false ;


create buf char : c, bl c, 254 allot
: :name ( c-addr u -- )
tuck [ buf 2 + ] literal swap move buf swap 2 + evaluate ;

create buf 256 allot
: :name ( c-addr u -- )
s" : " buf place buf append buf count evaluate ;

\ some incompatible jerk gave us a ( c-addr u -- ) :name !!!
: :name ( cstr wid -- )
get-current >r set-current count :name r> set-current ;

Why is :NAME ( cstr wid -- ) anyway? cstr->pair is a COUNT away; the
other direction isn't. There are perfectly good ANS words to let you
place a new word in a particular wordlist. novice.4th has fifteen
occurrences of GET-CURRENT :NAME , and then some ( ... wid -- ... )
words that pass the wid.

Hugh Aguilar

unread,
Jul 14, 2011, 9:41:40 PM7/14/11
to
On Jul 14, 3:38 am, Julian Fondren <ayrn...@gmail.com> wrote:
> On Jul 14, 12:22 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>
> > The same thing is true of :NAME --- I am just supporting a simple
> > system for associating more than one action to each datum --- I am not
> > attempting a full-blown OOP with messages being sent to the DOES> code
> > as strings.
>
> > Everything in my novice package is simple.
>
>   16  constant cstr-levels            \ how many CSTR> buffers there

I don't much like the way that <CSTR uses a circular buffer --- I
might change it to use the heap in the next release. I would keep a
list of <CSTR strings, so I can FREE them all --- that way I don't run
out of heap memory, but I also don't have an arbitrary limit on how
many strings can be active.

> Why is :NAME ( cstr wid -- ) anyway?  

You mean, why not an adr/cnt pair? Well, the string is usually
provided by <CSTR which returns a cstr (hence the name), so I
made :NAME accept a cstr. You are right though, that I could have
made :NAME accept an adr/cnt pair instead, and just use COUNT to get
there --- that would be somewhat more robust.

All in all, I think that my novice package is pretty simple. There is
an awful lot of code in there, so it is a wide target for criticism
--- but I'm proud of it. (note that I said "an awful lot of code" not
"a lot of awful code" lol)
See http://www.forth.org/novice.pdf for a discussion of some of the
better points.

Note that all of those xxx, words (they do a POSTPONE of the xxx word)
won't be necessary in my own language that I'm developing, as
something like that will be automatically provided by the compiler.

Aleksej Saushev

unread,
Jul 29, 2012, 3:02:01 PM7/29/12
to
Alex McDonald <bl...@rivadpm.com> writes:

> On Jun 15, 3:22О©╫pm, Mark Wills <markrobertwi...@yahoo.co.uk> wrote:
>> On Jun 15, 2:50О©╫pm, Alex McDonald <b...@rivadpm.com> wrote:
>> > On Jun 15, 2:10О©╫pm, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>> > > On Jun 15, 3:52О©╫am, Alex McDonald <b...@rivadpm.com> wrote:
>> > > > On Jun 15, 1:03О©╫am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>> > > > > On Jun 14, 12:01О©╫am, Julian Fondren <ayrn...@gmail.com> wrote:
>>
>> > > > > > Your proposal here is identical to your initial proposal, except that
>> > > > > > you've dropped your example from Current Practice, except that you've
>> > > > > > changed the name of the word. О©╫So you've just ignored all of the
>> > > > > > discussion about it, the distinction that was made between ALLOCATION
>> > > > > > and ALLOCATED , the discussion of some current practice, of some
>> > > > > > implementation strategies.
>>
>> > > > > I already said that what I'm presenting here is identical to what what
>> > > > > was presented and rejected earlier.
>>
>> > > > > I'm not ignoring the distinction between ALLOCATION (what was
>> > > > > requested of ALLOCATE or RESIZE) and ALLOCATED (what was actually
>> > > > > allocated, which would be >= to what was requested) --- I just don't
>> > > > > think the distinction is particularly important. The whole point of
>> > > > > this was to support CLONE-LIST. I have lists which have nodes of
>> > > > > various types. To make a copy of the list, I need to be able to
>> > > > > determine the size of each node because CMOVE> needs this size. I
>> > > > > don't really care if the size I get from ALLOCATION is the same size
>> > > > > that I originally requested, or is slightly larger, because CMOVE>
>> > > > > will work either way. CMOVE> might be slightly slower if it is copying
>> > > > > not only the data but a "tail" of garbage as well, but that is not an
>> > > > > issue to me.
>>
>> > > > > Currently in the novice package, I have rewritten all of the heap
>> > > > > memory words. The language is badly designed, else the application
>> > > > > programmer wouldn't be required to rewrite the basic functionality of
>> > > > > the language in order to support something as basic as linked lists. I
>> > > > > think the reason why there are so few Forth applications, is because
>> > > > > the Forthers spend way too much time dinking around with low-level
>> > > > > code that should have been provided already. This is also why Forth
>> > > > > applications are often hard to read --- because everybody implements
>> > > > > the low-level code differently from each other, and the programs seem
>> > > > > to be written in different languages --- "if you've seen one Forth,
>> > > > > you've seen one Forth."
>>
>> > > > > Keeping track of the size of the nodes when the nodes are created,
>> > > > > doesn't work very well. The constructor for the node must call the
>> > > > > constructor for the parent type first. That parent constructor sets
>> > > > > the node-size field in the node to the wrong value (too small). The
>> > > > > constructor then has to manually fix this node-size field with the
>> > > > > correct size. That is the way that I did it originally, and it was a
>> > > > > huge hassle. It was error-prone because I could easily write a
>> > > > > constructor and forget to do this manual fix-up, and not know about
>> > > > > this bug until later on when (if) I tried to run CLONE-LIST on the
>> > > > > list containing the node and failed to copy the entire node. Forcing
>> > > > > the application programmer to do this manually is just clumsy --- this
>> > > > > is low-level code that should be part of the language.
>>
>> > > > This is a fundamental design problem in your code, not a problem with
>> > > > the memory allocation words that Forth provides.
>>
>> > > > Many systems (Linux, BSD, every version of IBM mainframe systems to z/
>> > > > OS and others) do not provide any mechanism for discovering this
>> > > > length information. Here are the standard Linux kernel calls;
>>
>> > > > void *kmalloc( size_t size, int flags );
>> > > > void kfree( const void *objp );
>>
>> > > > There isn't any way of getting what you want from the system.
>>
>> > > > Effectively, what you are trying to do is push off a problem in your
>> > > > application code to a layer below you. That's not the correct
>> > > > response, which should be either to (1) redesign to remove the problem
>> > > > or (2) wrap the memory allocation functions -- effectively write your
>> > > > own, as you have done -- to store the information your application
>> > > > needs. That doesn't require an addition to the language
>> > > > specification.
>>
>> > > And the first B grade goes to --- Alex McDonald!
>>
>> > > I said at the beginning that my RfD violated *two* fundamental
>> > > principles of Forth-200x. This is the first principle violated:
>>
>> > > 1.) Gforth is written in C, and therefore it necessarily must have the
>> > > same limitations as C. The heap in C doesn't provide an ALLOCATION
>> > > function, and therefore the heap in Forth can't either.
>>
>> > > The fundamental disagreement between myself and Anton Ertl, is that he
>> > > believes that Forth is a toy interpreter written in C, and I believe
>> > > that Forth is a real language that is *better* than C. This is why he
>> > > gives me an F grade in Forth-200x.
>>
>> > You are sadly mistaken on several counts. There is no mechanism to get
>> > such information from many systems; please show me a system call that
>> > returns the information (specifically, the length allocated). Windows,
>> > BSD, Linux's SLAB SLOB SLUB.
>>
>> > I would like to see where Anton has ever said that Forth is a toy
>> > interpreter; or are you making stuff up again?
>>
>> > > > There isn't any way of getting what you want from the system.
>>
>> > > What a loser mentality! This reminds me of the old joke about the guy
>> > > who asked for directions to his goal and was told: "You can't get
>> > > there from here."
>>
>> > > Other languages run under these same systems (BSD, Linux, Windows,
>> > > etc.), and yet they work just fine. Factor, for example, has its own
>> > > heap system --- it doesn't rely on MALLOC and all of that other
>> > > garbage that comes with C.
>>
>> > AFAIK, Factor uses garbage collection, and it too has no way of
>> > telling you what length you previously allocated at a specific
>> > address. I'm struggling to think of a language (as opposed to library)
>> > that does.
>>
>> > BYW, here's GC in Forth;http://www.complang.tuwien.ac.at/forth/garbage-collection.zip.
>> > Oddly, it also runs on gforth, written in C.
>>
>> > > So long as Forth-200x is designed with the
>> > > constraint that it must support C implementations such as Gforth, then
>> > > Forth-200x will always be nothing more than a C wannabe --- Forth will
>> > > never be considered to be a better language than C, which is what
>> > > Chuck Moore wanted Forth to be from the very beginning (and why I got
>> > > interested in Forth way back in 1984). The C language is just a big
>> > > mish-mash of bad design decisions --- and one of them is that the heap
>> > > lacks an ALLOCATION function --- but why should Forth inherit all of
>> > > C's problems?
>>
>> > You really must start distinguishing between language and library.
>> > Java is a very small language supported by a huge set of libraries,
>> > and if you tried suggesting that feature X needs an addition to the
>> > language specification, you would get shot down in flames. In fact, a
>> > good language *minimizes language cruft, something that Chuck made
>> > abundantly clear over the years.
>>
>> > > I said at the beginning that there were *two* fundamental principles
>> > > of Forth-200x that my RfD violated. What was the other fundamental
>> > > principle violated? There is still room for another B grade to be
>> > > given out for the correct answer to this question.
>>
>> > Who cares? I certainly don't, since getting a B from someone who gets
>> > an F is hardly rewarding.
>>
>> Respectfully, you are sadly mistaken:
>>
>> "You are sadly mistaken on several counts. There is no mechanism to
>> get
>> such information from many systems; please show me a system call that
>> returns the information (specifically, the length allocated). Windows,
>> BSD, Linux's SLAB SLOB SLUB. "

PalmOS has it as system call.

>> You are approaching this from the mind-set that Forth HAS to sit on
>> top of an operating system. It doesn't. And it was never intended to
>> by the language's creator all those years ago. Indeed Forth's ideal
>> 'domain' isn't PC's and large systems at all. It's small embedded
>> systems, that don't need an operating system, as we all know. Surely,
>> the fact that a particular Forth system sits atop an OS is incidental?
>
> No, that is not my point. As a *design point, OSes do not provide the
> length of an allocated block. As a *design point, Forth's ALLOCATE
> does not return this information either, nor do several other
> languages, including C. It is, to be frank, superfluous, since
> generations of programmers at all levels have managed without such a
> feature. Those that can't are free to augment whatever memory
> management scheme they wish to use.

Thus, PalmOS (and, perhaps, MacOS too) designers must be idiots, in your opinion,
since <Core/System/MemoryMgr.h> reads, literally:

/******************************************************************************
*
* Copyright (c) 1994-2003 PalmSource, Inc. All rights reserved.
*
* File: MemoryMgr.h
*
* Release: Palm OS 5 SDK (68K) R3.
*
* Description:
* Include file for Memory Manager
*
*****************************************************************************/

...

//-------------------------------------------------------------------
// Pointer (Non-Movable) based Chunk Routines
//-------------------------------------------------------------------
MemPtr MemPtrNew(UInt32 size)
SYS_TRAP(sysTrapMemPtrNew);

#define MemPtrFree( p) \
MemChunkFree(p)

// Getting Attributes
MemHandle MemPtrRecoverHandle(MemPtr p)
SYS_TRAP(sysTrapMemPtrRecoverHandle);

UInt16 MemPtrFlags(MemPtr p)
SYS_TRAP(sysTrapMemPtrFlags);

UInt32 MemPtrSize(MemPtr p)
SYS_TRAP(sysTrapMemPtrSize);


Another popular allocator, Boehm GC, provides the function too:

/* Given a pointer to the base of an object, return its size in bytes. */
/* The returned size may be slightly larger than what was originally */
/* requested. */
GC_API size_t GC_CALL GC_size(const void * /* object_addr */);


Perhaps you should learn something from the real world outside Forth
rather than pull stupid arguments relating even to kernel programming
(which you don't know either, as it seems).


--
HE CE3OH...
It is loading more messages.
0 new messages