''The "lazy" command is now part of CritLib [http://www.equi4.com/critlib]'' ---- This demo is a self-contained package which supports creating values that are evaluated lazily, i.e. on the first time they are used. More exactly, "lazy" constructs a Tcl_Obj* value with no string representation. The first time the value is used, a previously specified command is run, the result of which is then used as string representation. The fact that such lazy evalution was applied is totally hidden, and one-shot only. An example: proc readfile {filename} { return [read [open $filename]] } file delete myfile.txt set grabit [lazy readfile myfile.txt] exec date myfile.txt puts $grabit The result will show as a timestamp, even though that information didn't exist at the time when $grabit was defined. There are numerous uses for this "delayed processing" mechanism, but I'm not yet sure it is working reliably. There have been some unexplained interactions (even though interpreter state *is* saved and restored). One known weakness, is that the code executed lazily may never throw an error (this makes the above example a bad one, btw). That may prove to be a big show stopper. There simply is no logical place to handle such an error condition. A related issue, is that the delayed call stashes away a copy of its Tcl interpreter, because even though it should not alter it, execution does require having such an interpreter context to work in. Source: ---- package require lazy proc yell {args} { puts stderr "YELL $args"; return $args } proc lazy_try {} { catch {lazy -peek yell} err puts "err = $err" puts [lazy yell bingo] set a [lazy yell one two three] puts "peek = [lazy -peek $a]" puts "eval = $a" puts "eval = [llength $a]" set ::errmsg "" puts "thrown = [lazy error bang!]" puts "caught = [lazy catch {error boom!} errmsg]" puts "errmsg = $::errmsg" set ::errorInfo "" set a [lazy error dontlook!] puts "peek a = [lazy -peek $a]" puts "errorInfo <[join [split $::errorInfo \n] { - }]>" string length $a puts "errorInfo <[join [split $::errorInfo \n] { - }]>" puts "eval a = $a" set a "" set b [catch {lazy error yes?} a] puts "errorInfo <[join [split $::errorInfo \n] { - }]>" puts "a = $a, b = $b" global one trace var one rwu [list yell trace] set one(1) un puts $one(1) unset one set two [lazy yell deux] puts "two #0" puts "peek [lazy -peek $two]" puts "two #1 $two" puts "two #2 $two" } lazy_try ---- Output (SuSE 7.1 Linux, PIII/650): ---- err = not a lazy object YELL bingo bingo peek = yell one two three YELL one two three eval = one two three eval = 3 thrown = bang! caught = 1 errmsg = boom! peek a = error dontlook! errorInfo <> errorInfo eval a = dontlook! errorInfo a = yes?, b = 0 YELL trace one 1 w YELL trace one 1 r un YELL trace one {} u two #0 peek yell deux YELL deux two #1 deux two #2 deux ----