FM : Here is a proc whose only goal is to "inline" one lmap loops, when its boundaries are known at compile time.
In short, it's about the kind of lmap we write just for convenience, to shorten the code, because we are lazy to write long command. For instance :
proc essai.1 {L} {
lmap i {1 2 3} {
lindex $L $i
}
}The optproc below just creates a proc that is removing the loop totally to produce a body like :
list [lindex $L 1] [lindex $L 2] [lindex $L 3]
Very simple proof of concept :
proc optproc {name args body} {
rename lmap _lmap
proc lmap args {
set body [lpop args]
set script {}
foreach {vars listval} $args {
if {! string match {$*} $listval} {
# not a variable : $listval"
if {! string match {\[*\]} $listval} {
# "not a command "
# "litteral loop :"
set script {list }
set len [llength $listval]
foreach val $listval {
foreach var $vars {
set string [string map [list \$$var $val] $body]
}
append script \ \[$string\]
}
}
}
}
return $script
}
set script [eval $body]
uplevel [list proc $name $args $script]
rename lmap {}
rename _lmap lmap
}And we can use it as :
optproc essai.2 {L} {
lmap i {1 2 3} {
lindex $L $i
}
}Then we can measure the difference :
set L {1 2 3 4 5 6}
timerate {essai.1 $L}
# 4.991574 µs/# 200337 # 200337 #/sec 999.997 net-ms
timerate {essai.2 $L}
0.445589 µs/# 2244217 # 2244219 #/sec 999.999 net-msThis kind of « convenience lmap » is more than one order of magnitude slower !
Is there any possibility to optimise the lmap code when the loop is known at compile time ?