Version 1 of Self-rewriting code

Updated 2006-04-26 14:39:09

Richard Suchenwirth 2006-04-26 - A question on comp.lang.tcl brought me to experiment with code that rewrites itself. The idea is that settings are not saved in a separate resource file, but in the script itself, as setting a global variable with the desired value. So the next time the script is run, the previously saved setting applies. Here's what I did:

 proc save {filename varlist} {
     set f [open $filename]
     set data [read $f]
     close $f
     set lines {}
     foreach line [split $data \n] {
          foreach var $varlist {
             if [regexp "^ *set $var " $line] {
                 set line [list set $var [set ::$var]]
             }
         }
         lappend lines $line
     }
     set f [open $filename w]
     puts $f [join $lines \n]
     close $f
 }

#-- Now for a testing demo:

 package require Tk

#-- We will test with this variable:

 set foo hello

 label  .1 -text foo: 
 entry  .2 -textvar foo  
 button .3 -text Save -command [list save [info script] foo]
 eval pack [winfo children .] -side left 

#-- Invaluable little helper for rapid restart:

 bind . <Escape> {exec wish $argv0 &; exit}

EMJ - 2006-04-26 - Aaaaargh! Self-modifying code, the slippery slope to certain unmaintainability! That of course is a remark from the distant past, when clever people wrote very fast but generally incomprehensible self-modifying assembly language. The warning is still valid, however - be careful!

For the stated purpose, it's not actually too bad, but I think I would use an alias or something rather than just set, in order to make the regex more discriminating. I guess it's simply the reverse of what tkbiff does, writing most of its code to its config file!


Category Example - Arts and crafts of Tcl-Tk programming