How to remove items from a list not by their position ([lreplace]) but by the actual content. My solution would be: proc K { x y } { set x } proc lremove { listvar string } { upvar $listvar in foreach item [K $in [set in [list]]] { if {[string equal $item $string]} { continue } lappend in $item } } which gives us % set a [list a b c a b c a b c] a b c a b c a b c % lremove a b % set a a c a c a c Is there any reason not to do it that way? Gotisch ---- [RS] proposes this built-in way, waving many flags :) % set a [lsearch -all -inline -not -exact $a b] a c a c a c ---- Todd A. Jacobs suggests this slightly more flexible version: # lremove ?-all? list pattern # # Removes matching elements from a list, and returns a new list. proc lremove {args} { if {[llength $args] < 2} { puts stderr {Wrong # args: should be "lremove ?-all? list pattern"} } set list [lindex $args end-1] set elements [lindex $args end] if [string match -all [lindex $args 0]] { foreach element $elements { set list [lsearch -all -inline -not -exact $list $element] } } else { # Using lreplace to truncate the list saves having to calculate # ranges or offsets from the indexed element. The trimming is # necessary in cases where the first or last element is the # indexed element. foreach element $elements { set idx [lsearch $list $element] set list [string trim \ "[lreplace $list $idx end] [lreplace $list 0 $idx]"] } } return $list } # Test cases. set foo {1 2 3 4 5 6 7 8 9 10} puts "Foo: [list $foo]" puts "Foo: replace one: [lremove $foo $argv]" puts "Foo: replace all: [lremove -all $foo $argv]" puts {} set bar {1 2 3 4 1 6 7 1 9 10} puts "Bar: [list $bar]" puts "Bar: replace one: [lremove $bar $argv]" puts "Bar: replace all: [lremove -all $bar $argv]" [dzach] ...but when I do : set bar {1 2 3 {} 4 1 6 7 1 9 10 {}} lremove -all $bar {} I get: 1 2 3 {} 4 1 6 7 1 9 10 {}