I have a problem in Tcl 8.4.
The concept of what I want to do is something like this:
- an existing built-in function,
builtinFn
, has one required argument and then a variable number of arguments (the number actually required depends on the first argument), so it could be called likebuiltinFn {arg_1a arg_1b} "two" "three" "four"
, say; - I want to provide a wrapping function,
wrapperFn
, that examines the first argument and then decomposes it into its constituent parts (arg_1a
andarg_1b
in the example above), and then callsbuiltinFn
with each individual constituent of the first argument separately, as inbuiltinFn {arg_1a} "two" "three" "four"
andbuiltinFn {arg_1b} "two" "three" "four"
.
No matter what I have tried, I get an error message, "Error: wrong # args:
" when I call builtinFn
from within wrapperFn
.
Simplified example of the problem
proc myInternal {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" turquoise4;
}
proc myWrapper {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
myInternal $var1 $args
}
Note: wherever you see mess
please read it as analogous to puts
— it just writes to the console in a neat way, with the option of specifying the colour of the text.
If I call myInternal one two three
, then the output is
var1 is one (length is 1), and args is two three (length is 2).
If I call myWrapper one two three
, then the output is
var1 is one (length is 1), and args is two three (length is 2).
var1 is one (length is 1), and args is {two three} (length is 1).
I have seen some posts that might be somehow relevant.
- TCL- How to interpret a string as multiple arguments in tcl procedures? [duplicate]
- TCL script: variable as argument of a function
Maybe this could be solved with {*}
in Tcl 8.5, but that is not available to me currently. I haven't figured out how to implement it with any other option such as list
or concat
or eval
.
Some other things I have tried that did not work:
proc myWrapper2 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
myInternal "$var1 $args"
}
myWrapper2 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one two three (length is 3), and args is (length is 0).
proc myWrapper3 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
myInternal $var1 [split $args]
}
myWrapper3 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one (length is 1), and args is {two three} (length is 1).
proc myWrapper4a {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
myInternal [list $var1 $args]
}
myWrapper4a one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one {two three} (length is 2), and args is (length is 0).
proc myWrapper4b {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
myInternal [concat $var1 $args]
}
myWrapper4b one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one two three (length is 3), and args is (length is 0).
proc myWrapper5 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
myInternal [puts "$var1 $args"]
}
myWrapper5 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is (length is 0), and args is (length is 0).
proc myWrapper6 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
eval myInternal $var1 [split $args ,]
}
myWrapper6 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one (length is 1), and args is {two three} (length is 1).
proc myWrapper7 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
eval myInternal [split "$var1 $args" ,]
}
myWrapper7 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one two three (length is 3), and args is (length is 0).
proc myWrapper8 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
eval {myInternal [split "$var1 $args" ,]}
}
myWrapper8 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is {one two three} (length is 1), and args is (length is 0).
proc myWrapper9 {var1 args} {
mess "var1 is $var1 (length is [llength $var1]), and args is $args (length is [llength $args]). \n" green4;
eval [linsert {} 0 myInternal $var1 $args]
}
myWrapper9 one two three
# Output:
# var1 is one (length is 1), and args is two three (length is 2).
# var1 is one (length is 1), and args is {two three} (length is 1).
In case it wasn't obvious, I need the second statement, which is written by myInternal
(invoked from myWrapper
), to exactly match the first statement, which is written 'directly' by myWrapper
.
Thanks for any tips!
—DIV