From: Fredrik Karlsson on 6 Jul 2010 09:29 Dear group, First of all, apologies to the members of #tcl - I posted this yesterday and got some answers, but not the whole story, so people may have seen this before. I would like to construct a list of lists (possibly containing lists.. and so on), and evaluate them as a command call. So, in this example: % set a [list puts [list string range "hejsan" 0 2]] puts {string range hejsan 0 2} % eval $a string range hejsan 0 2 I would instead like to get just "hej". How do I do this? And, why does the example above not work? Please enlighten me.. /Fredrik
From: Arjen Markus on 6 Jul 2010 10:01 On 6 jul, 15:29, Fredrik Karlsson <dargo...(a)gmail.com> wrote: > Dear group, > > First of all, apologies to the members of #tcl - I posted this > yesterday and got some answers, but not the whole story, so people may > have seen this before. > > I would like to construct a list of lists (possibly containing lists.. > and so on), and evaluate them as a command call. > So, in this example: > > % set a [list puts [list string range "hejsan" 0 2]] > puts {string range hejsan 0 2} > % eval $a > string range hejsan 0 2 > > I would instead like to get just "hej". > > How do I do this? > And, why does the example above not work? Please enlighten me.. > > /Fredrik The command that would do that is: puts [string range hejsan 0 2] - so [] instead of {}. So, if I understand you correctly, then each first element of a list is a command, all remaining elements are also commands in themselves? In that case, something like: proc recursive_eval {list} { if { [llength $list] <= 1 } { return $list } else { set arguments [recursive_eval [lrange $list 1 end]] return [eval [lindex $list 0] $arguments] } } (Note: untested) Regards, Arjen
From: Aric Bills on 6 Jul 2010 10:15 On Jul 6, 7:29 am, Fredrik Karlsson <dargo...(a)gmail.com> wrote: > Dear group, > > First of all, apologies to the members of #tcl - I posted this > yesterday and got some answers, but not the whole story, so people may > have seen this before. > > I would like to construct a list of lists (possibly containing lists.. > and so on), and evaluate them as a command call. > So, in this example: > > % set a [list puts [list string range "hejsan" 0 2]] > puts {string range hejsan 0 2} > % eval $a > string range hejsan 0 2 > > I would instead like to get just "hej". > > How do I do this? > And, why does the example above not work? Please enlighten me.. > > /Fredrik You want $a to contain the script puts [string range hejsan 0 2] but the way you have constructed it, it contains the script puts {string range hejsan 0 2} which behaves very differently. As you can read about in the "Tcl" man page (http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm), square brackets trigger command substitution, while curly braces prevent substitution (note that some commands [for example, if, foreach, switch] evaluate some of their arguments as Tcl code; that's different from command substitution). If you want to use [eval] on the string you construct, you need a way to construct it so that it contains square brackets where you want command substitution to occur. You could create a convenience command that would return a string surrounded by square brackets: proc bracket {args} { return "\[$args\]" } Then, you could construct your command with set a [list puts [bracket string range hejsan 0 2]]
From: Donal K. Fellows on 6 Jul 2010 17:20 On 6 July, 15:15, Aric Bills <aric.bi...(a)gmail.com> wrote: > If you want to use [eval] on the string you construct, you need a way > to construct it so that it contains square brackets where you want > command substitution to occur. You could create a convenience command > that would return a string surrounded by square brackets: > > proc bracket {args} { > return "\[$args\]" > } > set a [list puts [bracket string range hejsan 0 2]] That doesn't work, since it creates a value like: puts {[string range hejsan 0 2]} If you're going this way, you need to just do this: set a "puts [bracket string range hejsan 0 2]" But really if you're getting into this, you need to use a different way to construct your code that avoids such substitution complexities! For example, you use a helper procedure like this: proc printRange {string from to} { puts [string range $string $from $to] } set a [list printRange hejsan 0 2] With 8.5, you can use a lambda application instead (this cheats a little and uses args/{*} to shorten the code): set a [list apply {args {puts [string range {*}$args]}} hejsan 0 2] If the *real* code is getting one or more of those values at runtime, put the reading of it inside the helper/lambda. If not, you can actually store the script with the pre-substituted argument: set a [list puts [string range hejsan 0 2]] I guess from the fact that you're not doing this that you're needing to do some of this at the time of the [eval $a]... Donal.
From: Aric Bills on 6 Jul 2010 17:30 On Jul 6, 3:20 pm, "Donal K. Fellows" <donal.k.fell...(a)manchester.ac.uk> wrote: > On 6 July, 15:15, Aric Bills <aric.bi...(a)gmail.com> wrote: > > > If you want to use [eval] on the string you construct, you need a way > > to construct it so that it contains square brackets where you want > > command substitution to occur. You could create a convenience command > > that would return a string surrounded by square brackets: > > > proc bracket {args} { > > return "\[$args\]" > > } > > set a [list puts [bracket string range hejsan 0 2]] > > That doesn't work, since it creates a value like: > > puts {[string range hejsan 0 2]} Oops. Good point.
|
Next
|
Last
Pages: 1 2 Prev: ActiveTCL/Tablelist broken - still no solution Next: making executables from expect scripts |