Version 19 of linsert

Updated 2010-08-15 01:35:28 by AMG

linsert - insert elements into a list

http://www.purl.org/tcl/home/man/tcl8.5/TclCmd/linsert.htm


 linsert list index element1 ?element2 element3 ...?

A user asked why

    linsert $list 0 ..

did not result in .. being inserted into list.

Jesper Blommaskog ([email protected]) replied:

When doing list operations other than lappend, you must save the returned value. This applies to list, lindex, lrange, and lreplace at least.

In this example, you would perhaps want to do something like:

    set list [ linsert $list 0 .. ]

TFW Feb 20, 2004 - Inplace inserts

Often time we have a long list we want to insert "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 {*} command)

 proc lipinsert {_list index args} {
    upvar $_list list
    set list [linsert [K $list [set list ""]] $index {*}$args]
 }
 > set A [list 1 2 3]
 1 2 3
 > lipinsert A 1 a b c
 1 a b c 2 3

DKF 26 Oct 2004: The linsert command can be used to create a "lprepend" command that is like lappend except that it puts the values at the start of the list:

 proc lprepend {var args} {
    upvar 1 $var v
    lappend v   ;# Used as a an "is a list" check and to do var creation
    set v [linsert $v[set v {}] 0 {*}$args]
 }

(Note that this uses a variant on K that is more efficient in 8.5a2 but not so hot in previous versions)

Lars H: Has the above any advantage in comparison with

    set v [linsert $v [set v 0] {*}$args]

which is anyway slightly shorter? (OK, it can be used also where ther isn't another argument to place the [set v <whatever>] in, but what about those cases where an alternative exists? Is the idea of the example to establish a new idiom?)

TR - The easiest way is to use lreplace where the first index is -1 and the second is -2 ... like so:

 set myList [list 0 1 2]
 set myList [lreplace $myList -1 -2 5]
 -> 5 0 1 2

Lars H: You've missed the point entirely; the constructions above are about making sure linsert gets an unshared Tcl_Obj which it can modify in place.

Using linsert or lreplace for the acutal list operations makes no difference since they both call the same Tcl_ListObjReplace function, but lreplace has marginally more overhead (both at coding and run time) as there is an extra argument to write or interpret. Furthermore the canonical arguments that make lreplace $L $i $j behave like linsert $L 0 is i=0 and j=–1; any i less than 0 is clamped to 0, and any j less than the clamped i is treated as –1.


LES on 2005-10-27: I think that linsert is VERY different from lappend:

lappend listName string

linsert $actualList index string

If list "listName" doesn't exist, lappend creates it automatically. Quite unlike linsert, which only addresses actual lists, in the form of variable or explicit lists, but only existing lists. So it cannot create the list automatically.

After using lappend so often, I find linsert's syntax confusing and less useful.

I hope my point is clear: I am not complaining because linsert won't create the list automatically. I complain because one command requires the list's name whereas the other, despite its very similar objective, requires an actual list. That is the sort of annoying inconsistency we see so much in PHP, for example.


AMG: According to the man page, "[linsert] produces a new list from list by inserting all of the element arguments just before the index’th element of list." When doing end-relative indexing, this definition doesn't match the actual behavior. To explain how index is interpreted, the [linsert] man page refers to the [string index] man page, which says that end indicates the last element. From this I expect that [linsert {0 1 2} end x] will return {0 1 x 2}, the result of inserting x just before the end element of the list, which is 2. However, it actually returns {0 1 2 x}, so when doing end-relative indexing it inserts the new elements just after the indicated index. An alternative, more plausible explanation is that it inserts the new elements such that the first or last of the inserted elements will occupy the indicated index.

I made a sf.net bug to track this issue: [L1 ].

Please see my related comments on the lreplace page.


See also list, lappend, llength, lrange, lreplace, lsearch, lsort .


Tcl syntax help | Arts and crafts of Tcl-Tk programming