Version 7 of calcOnlyOnce

Updated 2012-01-06 13:07:03 by RLE

This really simple procedure is intended for long-running calculations:

 array set delayed {}
 proc calcOnlyOnce args {
  set args1\
    [concat [uplevel 1 namespace origin [lindex $args 0]] [lrange $args 1 end]]
  variable delayed
  if {[info exists delayed($args1)]} then {
    set delayed($args1)
  } else {
    set delayed($args1) [uplevel 1 $args]
  }
 }

Example usage -- this proc is slow:

 proc fib n {
  if {$n <= 1} then {
    return 1
  } else {
    set n1 [expr {$n-1}]
    set n2 [expr {$n-2}]
    expr {[fib $n1] + [fib $n2]}
  }
 }

Now test:

 % time {calcOnlyOnce fib 25} 1
 246325 microseconds per iteration
 % time {calcOnlyOnce fib 25} 1
 39 microseconds per iteration
 %  

The second call on same procedure was faster due to the fact that it was not re-calculated but "remembered" instead.


AM (17 august 2007) This is known as "memoization" - there are several Wiki pages on the subject.

AMG: Here's a link: memoizing

wdb Thanks for the hint ... before writing this page, I searched "delayed", "freeze" etc. Memoizing ... ok, I've learned a new word!