- lreplace list first last ?element element ...?
Examples edit
% lreplace {a b c} 0 0 @
@ b c
% lreplace {a b c} 1 1
a cIf the last argument of lreplace was made optional, one could essentially just alias ldelete to lreplace CmCc
TFW Feb 20, 2004 - Inplace replacementsOften time we have a long list we want to replace "in-place", that is without copying the list to a new altered list. Using the K combinator it is quite easy. (Note 8.5 is needed for the {expand} syntax)
escargo 15 Sep 2005 - Perhaps there is a better place for the following discussion, but this is where I saw a specific feature mentioned that I want to raise an issue about.List commands bounds checking and associated behaviorThe description above states (in part): "If first is less than zero then it refers to the first element of list."I see two problems with this:
AMG: While [lreplace] can be used to prepend elements to the beginning of a list, it cannot be used to append elements to the end of a list.
TFW Feb 20, 2004 - Inplace replacementsOften time we have a long list we want to replace "in-place", that is without copying the list to a new altered list. Using the K combinator it is quite easy. (Note 8.5 is needed for the {expand} syntax)
proc lipreplace {_list first last args} {
upvar $_list list
set list [lreplace [K $list [set list ""]] $first $last {expand}$args]
}
> set A [list 1 2 3]
1 2 3
> lipreplace A 1 end c d
1 c descargo 15 Sep 2005 - Perhaps there is a better place for the following discussion, but this is where I saw a specific feature mentioned that I want to raise an issue about.List commands bounds checking and associated behaviorThe description above states (in part): "If first is less than zero then it refers to the first element of list."I see two problems with this:
- What should the behavior be when indexing outside the bounds of a list?
- How does this behavior vary from other list operations?
AMG: While [lreplace] can be used to prepend elements to the beginning of a list, it cannot be used to append elements to the end of a list.
lreplace {0 1 2} 0 -1 x y z
→ x y z 0 1 2
lreplace {0 1 2} end -1 x y z
→ 0 1 x y z 2
lreplace {0 1 2} end+1 -1 x y z
→ error: list doesn't contain element end+1The man page says "if last is less than first, then any specified elements will be inserted into the list at the point specified by first with no elements being deleted." Like [lindex], it refers to [string index] for an explanation of the index notation and interpretation, so end is the last element, which is 2 in this case.Clearly, the insertion takes place just before the first element, even when first is end-relative. This is inconsistent with [linsert], which (despite the documentation) inserts just after the index'th element when index is end-relative.It is also inconsistent that [lreplace] accepts indexes before the beginning of the list but rejects indexes after the end of the list. [linsert] accepts out-of-bounds indexes in either direction.By the way, to prepend and append individual elements or entire lists to a list, several combinations of [concat], [list], and {*} can be used. Or if in-place modification is desired, use [lappend] with or without {*}, or use [lset] one element at a time. For example, all of the following combinations return {x y 0 1}:set elem1 0; set elem2 1
set list1 {x y}; set list2 {0 1}| Combine lists and elements using concat and list | concat $list1 [list $elem1] [list $elem2] |
| Combine lists using concat | concat $list1 $list2 |
| Combine lists and elements using list and {*} | list {*}$list1 $elem1 $elem2 |
| Combine lists using list and {*} | list {*}$list1 {*}$list2 |
| Append elements to a list using lappend | lappend list1 $elem1 $elem2 |
| Append a list to a list using lappend and {*} | lappend list1 {*}$list2 |
| Append elements to a list using lset | lset list1 end+1 $elem1; lset list1 end+1 $elem2 |
