From: Peter S. <pet...@sp...> - 2003-02-18 22:19:00
|
At 18:51 2003-02-18, Brent Welch wrote: >I think there is a 4th alternative, which is to make eval (and possibly >concat) more list aware. >Have eval use a list-aware version of concat if it gets multiple arguments. >In the past I have suggested the command name "leval" for this. >The above would be > >leval {exec $prog} $opts [getMoreopts] {$file $file2} Just to make sure we mean the same thing, here is my definition of leval: Assume we have 'lconcat' that makes true list concatenation. As 'eval ....' is equivalent to 'eval [concat ....]', 'leval ....' would be equivalent to 'eval [lconcat ....]'. Now lets assume $opts contains a two element list, with the elements {exec} and {$prog}, but with a non-pure string rep: set opts {exec $prog} How can leval know the difference between its first and second argument, so it can substitute the first and expand the second? leval {exec $prog} $opts [getMoreopts] {$file $file2} Well, it can't. This means that a list based leval can't make an extra round of substitution as eval does. So, leval would need to be used as: leval [list exec $prog] $opts [getMoreopts] [list $file $file2] And suddenly the improvement is not that great. It would be secure, object safe and efficient, and thus better than using eval, but it is still ugly. I agree that a real lconcat would be great, but leval just does not feel very good compared to expand. /Peter PS. A little lconcat/leval example: proc lconcat {args} { set result {} foreach arg $args { eval [linsert $arg 0 lappend result] } return $result } proc leval {args} { eval [eval [linsert $args 0 lconcat]] } # This should be equivalent to eval and is # just to emphasize the symmetry with leval. proc myeval {args} { eval [eval [linsert $args 0 concat]] } catch {console show} foreach p {leval myeval eval} { puts "Trying $p" set testlist [list a [expr 1.0/3.0] b] set apa [$p list $testlist] set bepa [lindex $apa 1] set cepa [expr {$bepa * 3.0}] puts "The double is now: $cepa" set testlist [list a [expr 1.0/3.0] b] set apa [$p [list list] $testlist] set bepa [lindex $apa 1] set cepa [expr {$bepa * 3.0}] puts "The double is now: $cepa" set testlist {a b ; puts hej} set apa [$p list $testlist] puts "The list is now: $apa" } |