Originated by Tom Wilkason on comp.lang.tcl. Modifications by [DGP]. if {[package vcompare [package provide Tcl] 8.4] < 0} { proc tcl::K {a b} {return $a} proc lset {listName index val} { upvar $listName list set list [lreplace [tcl::K $list [set list {}]] $index $index $val] } } ;# end if ---- [KPV] Does anybody have a version that works with multiple indices? [MG] Nov 12 2004 - Does this work? proc lset2 {listName args} { if { [llength $args] == "0" } { error "wrong # args: should be \"lset2 listVar index ?index...? value\"" } upvar $listName list if { [llength $args] == "1" || ([llength $args] == "2" && [llength [lindex $args 0]] == "0") } { set list [lindex $args [expr {[llength $args]=="1"?0:1}]] return $list; } set val [lindex $args end] foreach x [lrange $args 0 end-1] { set list [lreplace $list $x $x $val] } return $list; } [LIO] I couldn't seem to get the above to work correctly. I wrote a recursive version, the only difference to the actual lset (that I can think of) is it will not take the indeces as a single list (although it would be easy to add that in). if {[package vcompare [package provide Tcl] 8.4] < 0} { proc tcl::K {a b} {return $a} proc lset_r {list args val} { if { [llength $args] == "0" } { return $val } else { return [lreplace $list [lindex $args 0] [lindex $args 0] [lset_r [lindex $list [lindex $args 0]] [lrange $args 1 end] $val]] } } proc lset {listName args} { if { [llength $args] == "0" } { error "wrong # args: should be \"lset varName ?index...? newValue\"" } upvar $listName list set list [lset_r [tcl::K $list [set list {}]] [lrange $args 0 end-1] [lindex $args end]] } } [TP] 2005-01-12 I wrote this version a while back to use in Jacl. It probably could be optimized with the K tricks. Nor am I sure that it's fully compatible with the current 8.4 native lset. proc lset { varName args } { upvar 1 $varName list switch [llength $args] { 0 { error \ "wrong # args: should be \"lset listVar index ?index...? value\"" } 1 { set list [lindex $args 0] return $list } 2 { set index [lindex $args 0] if {[llength $index] > 1} { set value [lindex $args end] set list [eval lset list $index [list $value]] return $list } else { if {[regexp end $index]} { set index \ [expr ([llength $list]-1) [string range $index 3 end]] } if {$index < 0 || $index >= [llength $list]} { error "list index out of range" } set value [lindex $args end] set list [lreplace $list $index $index $value] return $list } } default { set index [lindex $args 0] if {[regexp end $index]} { set index [expr ([llength $list]-1) [string range $index 3 end]] } set rest [lrange $args 1 end-1] set value [lindex $args end] set sublist [lindex $list $index] set first [lrange $list 0 [expr {$index - 1}]] set last [lrange $list [expr {$index + 1}] end] set list $first lappend list [eval lset sublist $rest [list $value]] foreach l $last { lappend list $l } return $list } } } ---- [RS] 2005-02-20 hacked this up for the [iPaq] (Keuchel's port was 8.4a2, no [lset] yet): proc lset {_list args} { upvar 1 $_list list set list [lset0 $list [lrange $args 0 end-1] [lindex $args end]] } proc lset0 {list indices val} { if {[llength $indices]==0} {return $val} set p [lindex $indices 0] set list2 [lindex $list $p] set ind2 [lrange $indices 1 end] lreplace $list $p $p [lset0 $list2 $ind2 $val] }