Version 27 of lrepeat

Updated 2005-08-02 09:54:02 by suchenwi

lrepeat was defined in TIP 136 [L1 ] , which has been approved for incorporation into Tcl 8.5.0 .

Eventually, the doc will be here: http://www.tcl.tk/man/tcl8.5/TclCmd/lrepeat.htm

 lrepeat number element1 ?element2 element3 ...?

This command builds up a list by repeating elements. It will be a part of Tcl 8.5.0 . Note that Tcl 8.5 is available in an early developer form from ftp://ftp.tcl.tk/pub/tcl/nightly-cvs/tcl-*gz . Early access to Tk 8.5 is there as well.

An example of how it will work is

 lrepeat 3 a => a a a
 lrepeat 3 [lrepeat 3 0] => {0 0 0} {0 0 0} {0 0 0}

RS: Note the possible confusion with string repeat's syntax:

 % string repeat a 5
 aaaaa

FW: A forward-compatible version for versions before 8.5 is available in Additional list functions. Here's another ([RS 2005-08-02):

 proc lrepeat {n args} {if $n {eval concat $args [lrepeat [incr n -1] $args]}}

LES How is [lrepeat 3 a] different from [string repeat "a " 3]?

And how is lrepeat 3 [lrepeat 3 0] different from string repeat [list [string repeat "0 " 3]]] 3?

RS The first creates a list, while the second creates a string that can be parsed into a list. For short lists, this doesn't matter much, but I noticed extra time costs of about half a second when converting a 2000x2500 list-like string to a nested list.

LES Half a second? In the entire operation or each nested list? Mentioning once again that I am completely ignorant of C, I wonder if it wouldn't have been possible to rewrite string repeat and optimize it, using whatever method lrepeat uses to do its trick. This lrepeat command still strikes me as something a bit superfluous. I mean, something rather more suitable to the Bag of algorithms than the core.

Lars H: Much of the extra time RS mentions is probably spent on parsing the string into lists and allocating memory to hold the necessary data structures. Note that the string representation of a 2000x2500 elements nested list is at least 10MB (1 list element char + 1 separating space per list element; 2000*2500*2). The total memory required for the parsed nested list is at least one order of magnitude larger (each list element will use up a Tcl_Obj, which costs at least 24 bytes each). This is what you get when parsing the list from a string.

The situation using lrepeat can be much better, thanks to that repeated elements can share the same Tcl_Obj. The result of

  lrepeat 2000 [lrepeat 2500 a]

can be encoded using only three Tcl_Objs: First one for the "a". Second, a list Tcl_Obj that is the result of [lrepeat 2500 a] (which holds 2500 references to the "a" object). Third, another list Tcl_Obj for the result of the outer lrepeat (which in turn holds 2000 references to the result of the inner lrepeat). But it is true that this would be possible even for a Tcl implementation of lrepeat.

RS In fact, my application was rotating binary photo images by 90 degrees, where I had to create a target list of lists into which to lset the pixels - the speed gain came when I replaced a string repeat construct with nested for loops, not having lrepeat yet in 8.4.


LES Does anyone realize that one requires number - string while the other requires string - number, and that is an excellent method to prevent people from memorizing correct syntax? - RS pointed this out just 11 lines above :^) LES I thought you were just pointing out that one adds spaces in-between (list) and the other concatenates it all together (string).


Category Command