⍝ Function memoization: ⎕io←1 afib←{⎕io←0 ⍝ Naïve coding of ⍺-fibonacci number. ⍵∊⍳⍺:⍵ ⍝ small number: done, +/⍺ afib¨⍵-1+⍳⍺ ⍝ otherwise: sum of preceding ⍺ fib numbers. } 2 afib¨⍳10 ⍝ *slow* ⍺-fibonacci sequence. 1 1 2 3 5 8 13 21 34 55 afib←(afib)memo(cache ⍬) ⍝ Memoize afib. 2 afib¨⍳20 ⍝ *fast* ⍺-fibonacci sequence. 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 ⍝ Notice that afib is coded to use its own name explicitly, rather than '∇' ⍝ for the recursion. This is so that the recursive call references the newly- ⍝ assigned derived function, whereas '∇' would have referenced the original ⍝ function and circumvented the memoization. ⍝ Perhaps surprisingly, the cache can be relied upon to supply the "base values" ⍝ of the recursion, thus simplifying the initial function coding. fib←{ ⍝ Naïve coding of regular fibonacci number. +/fib¨⍵-1 2 ⍝ sum of preceding 2 fib numbers. } fib←(fib)memo(cache 2/¨0 1) ⍝ Cache pre-populated with base values. fib¨⍳20 ⍝ Fast fibonacci sequence. 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 div←÷ memo (cache ⍬) ⍝ Ambivalent operand function 2 div 7 ⍝ Dyadic use distinct from ... 0.2857142857 div 2 7 ⍝ ... monadic use. 0.5 0.1428571429 osc←{ ⍝ Oscillate - probably returns 1. 2|⍵:osc 1+3×⍵ ⍝ odd: triple 'n add-one, osc ⍵÷2 ⍝ even: halve. } ∆osc←cache⊂1 1 ⍝ Initialise cache for osc. osc←(osc)memo ∆osc ⍝ derive "fast" osc function. ∆osc.⎕nl 2 ⍝ cache-space contents. keys vals show←{ ⍝ Show cache <rslts ← args> ⍕↑⍵.(vals{⍺'←',⊂¯1↓⍵}¨keys) ⍝ (dropping extra rarg). } show ∆osc ⍝ Show initial cache. 1 ← 1 osc 2 ⍝ Apply derived function, extending cache. 1 show ∆osc ⍝ Show extended cache. 1 ← 1 1 ← 2 osc 3 ⍝ Apply function again. 1 show ∆osc ⍝ Show extended cache. 1 ← 1 1 ← 2 1 ← 4 1 ← 8 1 ← 16 1 ← 5 1 ← 10 1 ← 3 zap←{⎕ml←0 ⍝ Remove value ⍵ from cache ⍺. ⍺.{⎕ml←0 ⍝ within cache: mask←⍵∘≡¨↓⍉↑vals keys ⍝ mask of matches. {1}vals keys/⍨←⊂~mask ⍝ retain non-matches. }(⊃⍵)(1↓⍵,¯1↑⍵) ⍝ target value and key. } ∆osc∘zap¨(1 16)(1 10)(1 3) ⍝ Zap selected cache entries. 1 1 1 show ∆osc ⍝ Show compacted cache. 1 ← 1 1 ← 2 1 ← 4 1 ← 8 1 ← 5 osc 3 ⍝ Re-run function. 1 show ∆osc ⍝ Partially restored cache. 1 ← 1 1 ← 2 1 ← 4 1 ← 8 1 ← 5 1 ← 10 1 ← 3 +⎕ex'∆osc' ⍝ Seal access to osc's cache. 1 osc¨⍳10 ⍝ Derived function still operates normally. 1 1 1 1 1 1 1 1 1 1 ⍝∇ memo cache Back to: code Back to: Workspaces