\ Arnold Doray <
thinks...@gmail.com> wrote:
\ > Or do you have a simpler solution in mind?
\ Yes. Starting from the top:
\ The thing to keep in mind is that syntax isn't very important, but
\ semantics is. It's better not to start out with a fixed idea of what
\ the syntax is going to look like, but to solve the problem in the most
\ natural way and let the syntax be a result of the process.
\
\ We first need some sort of lookup table. The best design depends on
\ the funtion being memoized, but I'd like the interface to the table
\ to be:
\
\ SLOT ( key table - slot-address)
\
\ where the address returned points to a slot that's a tuple of two
\ integers, the key and the value.
\
\ As a simple example, I'll use a simple modulo hash for indexing into
\ the table. Like this:
: slot ( n table - slot)
dup cell+ >r @ mod abs 2 cells * r> + ;
\ A couple of field words for the key and the value:
: hash.key ( a - a') ;
: hash.value ( a - a') cell+ ;
\ And a word that creates a table:
hex 80000000 constant min-int decimal
: ,hashtable ( n)
dup ,
0 do min-int , 0 , loop ;
\ Now, I'll need a word that looks up a key in the table, and either
\ returns the value it found or executes a provided XT, updating the
\ table. Like EXECUTE, but with a memoization table:
: memoized-execute ( n table xt - n')
>r
over swap slot ( n slot)
2dup hash.key @ = if ( We found it)
hash.value @ swap r> 2drop exit then
( n slot) over r> execute
( n slot n') dup >r
-rot ( n' n slot) 2! r> ;
\ The stack manipulation in that word is rather fiddly and sorely
\ needs tidying up, but I hope it's fairly clear what's going on.
\
\ So, we now have all the pieces we need, and can define FIB:
defer (fib)
create fib-table 29 ,hashtable
: fib ( n - n') fib-table ['] (fib) memoized-execute ;
:noname ( n - n')
dup 1 > if dup 1- fib swap 2 - fib + then ;
is (fib)
\ That's OK, but it's not great. We've had to create a dummy (FIB)
\ definition and an auxiliary FIB-TABLE.
\
\ We really need a word that creates a memoizer that wraps a definition.
\ DOES> to the rescue:
: memoize ( n)
create 0 , ,hashtable
does> ( n) dup cell+ swap @ memoized-execute ;
\ Here's how it's used:
29 memoize fib
:noname ( n - n')
dup 1 > if dup 1- fib swap 2 - fib + then ;
' fib >body !
\ and
101 memoize M
101 memoize F
:noname
dup 0= if drop 1 exit then
dup 1- F M - ;
' F >body !
:noname
dup 0= if exit then
dup 1- M F - ;
' M >body !
\ And that will do, I think. You could add a bit of syntactic sugar
\ so that it looks a bit more like a colon definition, but I wouldn't.
\
\ "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis
\
\ Andrew.