Opinions?
I fail to see the need to generalize these. First, I (relatively)
rarely seem to iterate over an entire array.
In the largest public Forth program I wrote there are almost twice
the number of BEGIN..REPEAT loops as DO..LOOPS
the rare case of a data-dependent decrement). These 3 are:
Second, I already have some generalized high order functions for
mapping, reducing or FOREACHing complex structures. Can't say I used
them much since creating them - because my DO..LOOPs are usually so
simple, I can't see why I should be using them.
Use case one: raw arrays
- Set up the structure by address, #items and sizeof (item)
16 constant #items
32 constant /item
#items /item * array items
items #items /item * BOUNDS ?DO I ( do your thing) /item +LOOP
Use case two: indexed arrays
- Set up the structure by address, #items and sizeof (item)
- Add a DOES> definition that returns the address
16 constant #items
32 constant /item
#items /item * array items does> swap /item * + ;
#items 0 ?DO I items ( do your thing) LOOP
Use case three: use TH (or equivalent) to do the indexing
- TH only works with CELLS, but it is useful ( : TH CELLS + ; )
IMHO it is just some syntactic sugar - which won't speed up things anyway.
In that regard, I'd rather use FOREACH, since that one exposes the
address anyway and gets rid of the dirty details as well:
[: ( do your thing) ;] items #items /item FOREACH
I was going to mention that a good (or possibly the only) reason to use >iterators (like FOREACH) is when the data is organized in lists. However,
on reflection, it is possible to avoid lists by adding an indexing array
(at the cost of one indirection). Any idea if that would be significantly >faster?
The disadvantage of a simple array would be that it becomes too small or
is too large (in case of lists the number of items is probably dynamic).
variable p inlined
: p@ p @ ; inlined
: p++ 2 p +! ; inlined
: p@++ p@ p++ ; inlined
: r>p r@ p ! ; inlined
: !p>r p @ >r p ! ; inlined
( addr u ) swap !p>r
for
p@++ ...
next r>p
Of course the P words are coded efficiently in assembler.
On 26/01/2024 3:29 am, Anton Ertl wrote:
oh2aun@gmail.com (FFmike) writes:
variable p inlined
: p@ p @ ; inlined
: p++ 2 p +! ; inlined
: p@++ p@ p++ ; inlined
: r>p r@ p ! ; inlined
: !p>r p @ >r p ! ; inlined
( addr u ) swap !p>r
for
p@++ ...
next r>p
Of course the P words are coded efficiently in assembler.
This reminds me of Bernd Paysan's OOF and Mini-OOF2, where he has a
current object pointer that he explicitly sets with >O (similar to
your !P>R), saving the old object pointer on the return stack, and he
restores the old object pointer with O> (similar to your R>P). Most
others (including me) prefer the setting of the object pointer
automatically when a method is entered and restoring it automatically
when the method is left, though.
Then there's Moore's address registers where saving/restoring is based
on need rather than at every turn.
( addr count stride ) MEM+DO ... MEM+LOOP
( addr count stride ) MEM-DO ... MEM-LOOP
And maybe have a word
: ARRAY>MEM ( uelems uelemsize -- ubytes uelemsize )
tuck * swap ;
(Or maybe have a generic ANYLOOP (whatever it's name) that produces
the right match for the ...DO)
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 475 |
Nodes: | 16 (2 / 14) |
Uptime: | 19:26:26 |
Calls: | 9,487 |
Calls today: | 6 |
Files: | 13,617 |
Messages: | 6,121,093 |