Page 1 of 1
problem in understanding a definition and whats going on
Posted: Wed Apr 23, 2014 6:37 pm
by mkl0815
creating the sum of all numbers that are on the stack can be done by
Code: Select all
: sum depth 0 swap 0 do + loop ; redefined sum ok
1 2 3 4 sum . 10 ok
It works fine, but I have a problem understanding why the inner "swap 0" is needed.
Lets assume that 1 2 3 4 are already on the stack.
invoking "sum" executes "depth" first, putting the number "4" on the stack, that is used as limit for the loop.
after that a "0" is put on the stack, defining the index to start with. so the loop should run from 0 to 3 (4 times).
the "do" word takes both upper numbers (4 and 0) from the stack and runs the loop, that should add the remaining numbers on the stack.
That works fine (without the additional "swap 0" if I write
Code: Select all
: sum depth 1 do + loop ; redefined sum ok
1 2 3 4 sum . 10 ok
But why? Because the inner loop should only run from 1 to (depth-1)
Testing with:
Code: Select all
: test 3 0 do 1 loop ; redefined test ok
test .s <3> 1 1 1 ok
Showing that with 3 and 0 as limit and index do ... loop runs 3 times.
Can someone help me to understand that?
It is clear that the additional "swap 0" adds another number on the stack (0) that is not affecting the sum, but takes care that the stack is not empty before the loop ends.
But why is in the "sum" definition the loop is running one cycle more then in my "test" definition?
Mario.
Re: problem in understanding a definition and whats going on
Posted: Wed Apr 23, 2014 6:58 pm
by GARTHWILSON
creating the sum of all numbers that are on the stack can be done by
Code: Select all
: sum depth 0 swap 0 do + loop ; redefined sum ok
1 2 3 4 sum . 10 ok
It works fine, but I have a problem understanding why the inner "swap 0" is needed.
It starts with the 0 to add the first number to. So the next thing is that <anything1> <anything2> SWAP looks strange, and the first reaction is, "Why not just reverse the order to <anything2> <anything1> so you don't have to SWAP?"; but here we have DEPTH, and putting the 0 on first will give you a different result when you do DEPTH. You could do 0 DEPTH 1- which would come out the same length and approximately the same speed.
In your other situation, you can add the first two numbers together to start, instead of adding the first one to 0 and then the second one to the first result. If the stack only had one cell on it though, you'd have an underflow.
Re: problem in understanding a definition and whats going on
Posted: Wed Apr 23, 2014 7:17 pm
by mkl0815
Ok, I understand that adding an additional 0 to the stack prevents a stack underrun if only one numer is on the stack.
But it still not clear to me why the loop construct is taking one more cycle than my "test" definition.
To prevent the "only one numer" problem, I can write:
Code: Select all
: sum 0 depth 1 do + loop ; ok
1 sum . 1 ok
1 2 sum . 3 ok
Ok, but why do I need to loop from "1" to DEPTH instead of "0" to DEPTH?
Re: problem in understanding a definition and whats going on
Posted: Wed Apr 23, 2014 7:58 pm
by GARTHWILSON
Since you already put the 0 on the stack, DEPTH gives you one more than you had when you called SUM. So if you had two cells on the stack, the 0 makes for three, so DEPTH gives you a 3, not a 2, so you're going 3 1 DO instead of 2 0 DO. (I hope I'm understanting the question.)
For non-Forthers: If <to> <from> DO seems strange (as opposed to BASIC's FOR <from> <to>), think of gifts, where the label says TO: <name1>, and underneath, FROM: <name2>.
Re: problem in understanding a definition and whats going on
Posted: Thu Apr 24, 2014 12:40 am
by GARTHWILSON
What you have may be an interesting exercise, but it's not of any real practical use since it excludes having any other stuff underneath, pending futher operations when you unnest. An idea I've used from Forth Dimensions is { <cell1> <cell2> <cell3> etc. }. The values can be literals, or they can be fetched or calculated between the { and the } . The { stores the depth in a variable BEG_DEPTH, then you add any number of cells you want, and the } takes the depth again and subtracts the contents of BEG_DEPTH to know how many cells you added, and puts the result on the stack. The May/Jun 1997 issue of FD had SET_OF to use like CASE_OF in a CASE statement, so you can say in essence, "In the case of the number on the top of the stack being equal to any of these, do this..." A usage example would be:
Code: Select all
<do stuff> \ something that leaves a cell on the stack
CASE \ to determine what you do next
A0 CASE_OF <do stuff> END_OF \ In the case of it being A0, do this.
{ 13 16 20 27 } SET_OF <do stuff> END_OF \ If it's any of these numbers, do this.
50 7F RANGE_OF <do stuff> END_OF \ If it's in the range of 50 to 7F, do this.
END_CASE \ In any other case, take no action.
BTW, those are curly braces, although they hardly look like it on my monitor.
Re: problem in understanding a definition and whats going on
Posted: Thu Apr 24, 2014 3:21 am
by mkl0815
Since you already put the 0 on the stack, DEPTH gives you one more than you had when you called SUM. So if you had two cells on the stack, the 0 makes for three, so DEPTH gives you a 3, not a 2, so you're going 3 1 DO instead of 2 0 DO. (I hope I'm understanting the question.)
OMG, it's so simple. Adding 3 numbers takes only 2 steps. Adding the first two numbers and then adding the result to the third number. It has nothing to do with forth. It's just simple logic. So having a "3 0 do + loop" runs three times. But at the third step there's nothing to add on the stack any more, because only one number left (the result).
Thanks for pointing to the right direction
Mario.
Re: problem in understanding a definition and whats going on
Posted: Thu Apr 24, 2014 1:01 pm
by chitselb
creating the sum of all numbers that are on the stack can be done by
Code: Select all
: sum depth 0 swap 0 do + loop ; redefined sum ok
1 2 3 4 sum . 10 ok
It works fine, but I have a problem understanding why the inner "swap 0" is needed.
Code: Select all
: sum depth 1 do + loop ; redefined sum ok
1 2 3 4 sum . 10 ok
It is clear that the additional "swap 0" adds another number on the stack (0) that is not affecting the sum, but takes care that the stack is not empty before the loop ends.
But why is in the "sum" definition the loop is running one cycle more then in my "test" definition?
Mario.
What helps me sometimes is to unfold the source and add a stack diagram after each word, e.g.
Code: Select all
: sum ( n[depth] n[4] n[3] n[2] n[1] -- sum }
depth ( n[depth] n[4] n[3] n[2] n[1] depth }
0 ( n[depth] n[4] n[3] n[2] n[1] depth 0 }
swap ( n[depth] n[4] n[3] n[2] n[1] 0 depth }
0 ( n[depth] n[4] n[3] n[2] n[1] 0 depth 0 }
do
+ ( n[depth] n[4] n[3] n[2] 0+n[i] ; iterates "depth" times )
loop ; ( -- sum)
Re: problem in understanding a definition and whats going on
Posted: Sun Aug 12, 2018 7:56 pm
by JimBoyd
What you have may be an interesting exercise, but it's not of any real practical use since it excludes having any other stuff underneath, pending futher operations when you unnest. An idea I've used from Forth Dimensions is { <cell1> <cell2> <cell3> etc. }. The values can be literals, or they can be fetched or calculated between the { and the } .
The Commodore 64 lacks curly braces so I use
<[ and
]>.