I encountered problem to pass variable to proc. Pls see below code:
package require Tk
package require BWidget
source test_multiline_text_entry.tcl
. config -bd 3 -relief flat
proc proc1 {cur_win2} {
set cur_win1 [frame $cur_win2.newwin]
pack $cur_win1 -side bottom
#with below two command which don't use variable , then no problem
# text $cur_win1.txt2 -height 5 -yscrollcommand {.f.newwin.sb1 set}
# scrollbar .f.newwin.sb1 -command {.f.newwin.txt2 yview}
#with below two command which are using variable in command, them
system cannot display it and stop silently
text $cur_win1.txt2 -height 5 -yscrollcommand {$cur_win1.sb1 set}
scrollbar $cur_win1.sb1 -command {$cur_win1.txt2 yview}
pack $cur_win1.txt2 -side left
pack $cur_win1.sb1 -side right
}
set cur_win0 [frame .f -bg white]
pack .f -fill both -expand 1
frame .f.oldwin -bg white
pack .f.oldwin -side top
entry .f.oldwin.a1 -textvariable a1
text .f.oldwin.txt1 -height 5 -yscrollcommand {.f.oldwin.sb set}
scrollbar .f.oldwin.sb -orient vertical -command {.f.oldwin.txt1 yview}
pack .f.oldwin.txt1 -side left -fill both -expand true
pack .f.oldwin.sb -side right -fill y
proc1 $cur_win0
anybody can tell me what's the reason? Thanks a lot
Try:
text $cur_win1.txt2 -height 5 -yscrollcommand [list $cur_win1.sb1 set]
scrollbar $cur_win1.sb1 -command [$cur_win1.txt2 yview]
You **really** need try to understand Tcl/Tk syntax -- read
http://www.tcl.tk/man/tcl8.4/TclCmd/Tcl.htm !!!
Bruce
Should be:
text $cur_win1.txt2 -height 5 -yscrollcommand "$cur_win1.sb1 set"
scrollbar $cur_win1.sb1 -command "$cur_win1.txt2 yview"
or some people prefer:
text $cur_win1.txt2 -height 5 -yscrollcommand [list $cur_win1.sb1
set]
scrollbar $cur_win1.sb1 -command [list $cur_win1.txt2 yview]
I prefer the former. When you use {} tcl treats the content as a
literal string and does nothing to its content. Using "" allows
substitution.
Ob-Nitpick:
scrollbar $cur_win1.sb1 -command [list $cur_win1.txt2 yview]
R'
The [list] form will always work, the "quote" form will only work if
there are no spaces or other special TCL characters in the widget
name.
R'
I used to prefer double quotes too, but now I always go for [list ...]
as a quoting system because it produces predictable (and correct)
results every time, as opposed to double quotes which have a nasty
tendency to go wrong in demos to your boss (e.g. when you try a filename
with a space in it...)
Remember, in robust software engineering it is paranoia that wins!
Donal.
i've used both; right-now i do prefer subst:
scrollbar $cur_win1.sb1 -command [subst {$cur_win1.txt2 yview}]
Subst provides finer control on what has to be substituted and
the formatted code is much more readable than [list] and "".
Use format if the code-parsing is to complex for subst:
scrollbar $cur_win1.sb1 -command [format {%1$s.txt2 yview} $cur_win1]
-roger
I can only speak for myself here, of course, but I've found that nearly
every time I want something other than that which is done through basic
use of [list], it is easest to do it using a helper procedure that is
invoked by the simple thing constructed using [list]. It just manages to
save more of my hair that way. :-) (The exceptions do not apply to the
use of Tk, FWIW, but rather in certain kinds of automated source code
generation, a much more exotic use.)
Donal.
Interesting. Whenever I see the use of subst in someone else's code (I'm
not sure if I've ever used subst more than once or twice in my own
code...), my first thought is "oh, they obviously have needs that can't
be handled by normal use of quotes or list", and I go hunting for the
hidden meaning behind the choice of subst.
Often I'm quite surprised that there is no hidden meaning and I'm left
scratching my head wondering why they didn't pick something more
straight-forward. I also have to look long and hard at the code to make
sure there's not some hidden side effect waiting to bite me.
I'll agree with Donal in a subsequent post: I much prefer using list,
and if list won't work I use a helper proc rather than introduce some
other sort of quoting. At least, I think that's a proper paraphrase of
what Donal said.
But, no worries. We all have our preferences and idiosyncrasies. If it
works for you, that's often reason enough to pick one method over
another. Personally though, I'd never recommend subst to beginners.
? That's no nit; it's simply a mistake to have
"... -command [$cur_win1.txt yview]". Gerald
knows better, and I assume it's merely a typo-
graphical mistake introduced along the way.
Makes the reviewer wonder `why doesn't he use the standard idiom'?
Again, if $cur_win1 should contain special charcters, this will fail.
set cur_win1 {.foo bar}
toplevel $cur_win1
text $cur_win1.txt2
scrollbar $cur_win1.sb1 -command [subst {$cur_win1.txt2 yview}]
pack $cur_win1.txt2 $cur_win1.sb1
Invoking the scrollbar gives you
ambiguous command name ".foo": {.foo bar} {.foo bar.sb1} {.foo bar.txt2}
while executing
".foo bar.txt2 yview -1"
("uplevel" body line 1)
invoked from within
Pray that nobody names their widgets
set cur_win1 {.foo [exec rm -f $::env(HOME)]}
When using 'list', all this is a non-issue.
R'
Of course it was a typo!
That's a good thing to pray for anyway; that's *very* twisted and not at
all Tcl-ish at the same time. Try:
set cur_win1 {.foo [file delete -force ~/.]}
Donal.
*Hey*, at least *I* was trying to prevent the unsuspicious Windows
crowd shooting themselves in the foot¹ ;-)
R'
---
¹ if they hadn't installed cygwin, that is².
² but in that case they would probably know what they're doing.
Tochee ;-)
scrollbar $cur_win1.sb1 -command [subst {{$cur_win1.txt2} yview}]
It's always possible to produce something twisted like
"set cur_win1 {.foo [exec rm -f $::env(HOME)]}"...
The best way to avoid "shooting into your own foot" is by writing
readable code.
In this respect: list is better than "", but limited to one line;
more will make it as unreadable as using "".
-roger
Same problem, just use a curly in the cur_win1 name, gives you an
'unmatched paren' error when the scrollbar is invoked.
You will have a hell of a time finding these errors once they
manifest, since usually they show up when something completely
unrelated takes place (upgrade of some other package, OS release or
whatever).
| In this respect: list is better than "", but limited to one line;
| more will make it as unreadable as using "".
No, it isn't. If you need more than one command, you are supposed to
use a helper func anyway instead of
-command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
'nuff said, EOT4me.
R'
... tcl can't source such a script (unmatched curly braces), has nothing
to do with list or substitutions.
> You will have a hell of a time finding these errors once they
> manifest, since usually they show up when something completely
> unrelated takes place (upgrade of some other package, OS release or
> whatever).
... not an argument!
My ability to foretell the future is to restricted for countering this
kind of statement, sorry.
> | In this respect: list is better than "", but limited to one line;
> | more will make it as unreadable as using "".
>
> No, it isn't. If you need more than one command, you are supposed to
> use a helper func anyway instead of
> -command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
You agreed --fine.
-roger
set happyMoustache ":-\{)"
set sadMoustache ":-\{("
button .$happyMoustache -text $happyMoustache -command \
[list .$happyMoustache configure -bg green]
button .$sadMoustache -text $sadMoustache -command \
[subst {{.$sadMoustache} configure -bg red}]
pack .$happyMoustache .$sadMoustache
Works just fine for me, except that pushing the sad mustachioed face
produces an error, perhaps that's why he's sad... It certainly has
everything to do with lists though. Because if you then do:
.$sadMoustache configure -command \
[list .$sadMoustache configure -bg red]
It works.
>
>> You will have a hell of a time finding these errors once they
>> manifest, since usually they show up when something completely
>> unrelated takes place (upgrade of some other package, OS release or
>> whatever).
>
>
> ... not an argument!
> My ability to foretell the future is to restricted for countering this
> kind of statement, sorry.
>
It is an argument for exactly the reason you give: If you are unable to
predict the future, is it wiser to use the construct that is guaranteed
to work, or the one that might break? Obviously if you can see the
future perfectly, and know that no-one will ever use your code in an odd
way, then the unsafe method *MIGHT* be ok... But you can't, so it is a
good idea to do it right, and doing it right involves using list.
>
>> | In this respect: list is better than "", but limited to one line;
>> | more will make it as unreadable as using "".
>>
>> No, it isn't. If you need more than one command, you are supposed to
>> use a helper func anyway instead of
>> -command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
>
>
> You agreed --fine.
>
> -roger
>
I'm not sure he did agree. Just in case, the simple rules are:
1) Use list to build the command.
2) If you need more than one command, wrap it in a proc, and use list to
build the call to the proc.
The complex rule is:
1) Follow the simple rules.
And now it's time for more painkillers and to return under my warm and
cozy rock...
Dan "Surf by Corrections" Smart
You are right tcl can source it.
>
>>
>>> You will have a hell of a time finding these errors once they
>>> manifest, since usually they show up when something completely
>>> unrelated takes place (upgrade of some other package, OS release or
>>> whatever).
>>
>>
>>
>> ... not an argument!
>> My ability to foretell the future is to restricted for countering this
>> kind of statement, sorry.
>>
> It is an argument for exactly the reason you give: If you are unable to
> predict the future, is it wiser to use the construct that is guaranteed
> to work, or the one that might break? Obviously if you can see the
> future perfectly, and know that no-one will ever use your code in an odd
> way, then the unsafe method *MIGHT* be ok... But you can't, so it is a
> good idea to do it right, and doing it right involves using list.
The worst kind of errors are those which go undetected.
Using curly braces within window names is such an error -- i think you
will agree with me.
Tk has been written for the X11 environment, therefore
the X11 documentation may serve as reference (excerpt from LocalDB):
X Locale Database only accepts XPCS, the X Portable Character Set. The
reserved symbols are; the quotation mark("), the number sign (#), the
semicolon(;), the backslash(\), the left brace({) and the right brace(}).
...
www.x.org/X11R6.8.1/docs/i18n/LocaleDB.pdf
Unfortunatly the document does not exclude spaces from being used within
window names (instances), but the Xlib Programming Manual states on page
454:
... a name is often made up of multiple words, concatenated without
spaces, ...
Although X11 does not disallow using spaces wthin window names, in Tk it
is an error. If you specify a resource, inside a resource file, for a
name with a space in it, it will not being added to the option database
, when using option readfile <resource file>.
In essence all presented examples against subst are errors themself,
which may remain uncovered when using the the list idiom!
>>
>>> | In this respect: list is better than "", but limited to one line;
>>> | more will make it as unreadable as using "".
>>>
>>> No, it isn't. If you need more than one command, you are supposed to
>>> use a helper func anyway instead of
>>> -command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
>>
>>
>>
>> You agreed --fine.
>>
>> -roger
>>
> I'm not sure he did agree. Just in case, the simple rules are:
> 1) Use list to build the command.
> 2) If you need more than one command, wrap it in a proc, and use list to
> build the call to the proc.
>
> The complex rule is:
> 1) Follow the simple rules.
>
> And now it's time for more painkillers and to return under my warm and
> cozy rock...
>
> Dan "Surf by Corrections" Smart
Well you do agree, too -- again fine.
If you really want to use something like:
-command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
then at last use subst:
subst -novariables {
[list command1 $foo $bar];
[list command2 $foo $bar]
}
i guess we are through now?
have a nice day
-roger
> The worst kind of errors are those which go undetected.
> Using curly braces within window names is such an error -- i think you
> will agree with me.
>
I also agree that using odd names for widget paths is a recipe for
disaster, but I can see instances where it's not entirely without merit.
For example, one might write a proc that accepts a name from the user
and creates a form. Within that proc it could be argued that it makes
sense (or at least is convenient to the lazy programmer) to name the
containing frame with the name given by the user.
In such a scenario, it follows that the user could enter a name like "My
personal data", or anything else that, strictly speaking, is not a good
choice for a widget name.
proc new_form {name args} {
text .container.$name ...
scrollbar .container.scroll-$name ...
}
This is a case where using anything other than list to form the value of
an -xscrollcommand option could be trouble.
I think the point many of us are making is that even though you can use
double quotes or subst or all sorts of different solutions, it's best to
get in the habit of always using list or a helper proc so you don't have
to think in every situation "is it ok to take a chance in this context?"
Personally, I try to write code that works not just in cases that are
likely to happen, but in cases that are possible to happen. It's not
likely that widget names will contain spaces, but it's possible.
> Although X11 does not disallow using spaces wthin window names, in Tk it
> is an error.
No, it is not an error, to wit:
% label ".hello world" -text "Hello, world"
.hello world
% pack ".hello world"
% winfo exists ".hello world"
1
> If you specify a resource, inside a resource file, for a
> name with a space in it, it will not being added to the option database
> , when using option readfile <resource file>.
That much is probably true, though I haven't verified it. I don't use
resource files myself. They are a bit too user-unfriendly for my tastes,
especially in a Windows or Macintosh context.
>
> If you really want to use something like:
> -command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
>
> then at last use subst:
>
> subst -novariables {
> [list command1 $foo $bar];
> [list command2 $foo $bar]
> }
>
>
> i guess we are through now?
>
I can't figure out why subst is necessary or better in this situation,
but there's no point in trying to convince you otherwise. It's good,
however, that once in a while we hash out the pros and cons of various
techniques so people new to the langage can see the trade-offs of
various approaches to solving a particular problem (assuming they read
this deep into threads...)
What we are discussing here is how to create a TCL script that can
be dynamically used by any TCL commands that accept scripts as arguments.
Among others there are:
eval
uplevel
$widget -command
and others.
A script is just a string with a special formatting in it that conforms
to the 11 rules (or are they 12 now?)
You can create a script like this with any command that can deal with
strings (most in TCL), like list, subst, format or directly with "" or {}
If the string is literal and does not need substitution, there should not
be problem ( we know the 11-12 rules, don't we?). If we need substitution,
we need to be sure that after substitution, the string continues to be a
valid TCL script.
As others have noted, the easiest way of making a correct substitution
is by using list:
set script [list cmd $arg1 $arg2]
we can be sure that script will be a command with two arguments, for any
value of
variables arg1 and arg2
For me it is OK too, if we need two commands:
set script "[list cmd $arg1 $arg2] ; [list cmd $arg1 $arg2]"
for more complex things it is advised to create a proc and
call that proc from the script.
For very special cases, and normally not advised, there are other
possibilities:
set script {
cmd1 $v1 $v2
cmd2 ARG1 ARG2
}
set script [string map [list ARG1 [list $arg1] ARG2 [list $arg2] $script]
This way, some variables can be substituted and others no. But in
general this
technique tends to be too complex and error prone and it is better to
create a
helper proc.
More information on this can be found here:
Ramon Ribó
En Sun, 13 Nov 2005 14:27:05 +0100, Arndt Roger Schneider
<roger.s...@addcom.de> escribió:
--
Compass Ing. y Sistemas Dr. Ramon Ribo
http://www.compassis.com ram...@compassis.com
c/ Tuset, 8 7-2 tel. +34 93 218 19 89
08006 Barcelona, Spain fax. +34 93 396 97 46
> Remember, in robust software engineering it is paranoia that wins!
QOTW-worthy wisdom.
If it is going to be more than **one** ***short*** line -- than write a
procedure and call the procedure with parameters!!!
[snip]
> I also agree that using odd names for widget paths is a recipe for
> disaster, but I can see instances where it's not entirely without merit.
> For example, one might write a proc that accepts a name from the user
> and creates a form. Within that proc it could be argued that it makes
> sense (or at least is convenient to the lazy programmer) to name the
> containing frame with the name given by the user.
>
> In such a scenario, it follows that the user could enter a name like "My
> personal data", or anything else that, strictly speaking, is not a good
> choice for a widget name.
>
> proc new_form {name args} {
> text .container.$name ...
> scrollbar .container.scroll-$name ...
> }
>
> This is a case where using anything other than list to form the value of
> an -xscrollcommand option could be trouble.
>
> I think the point many of us are making is that even though you can use
> double quotes or subst or all sorts of different solutions, it's best to
> get in the habit of always using list or a helper proc so you don't have
> to think in every situation "is it ok to take a chance in this context?"
>
> Personally, I try to write code that works not just in cases that are
> likely to happen, but in cases that are possible to happen. It's not
> likely that widget names will contain spaces, but it's possible.
[snip]
Hi Bryan,
i see why you want to inoculate code against such abuses.
In my first post i did state, that my primary concern is readablity.
The thread did later on elaborate on entirly differnet things, a
sidetrack in fact.
I think this sidetrack has reached an dead end --i did profit from it,
thanks to everyone how did already partake.
Read the next (longish) posting which will discuss my objectives in
detail (concering subst).
-roger
In both cases there was always one thought nagging in my mind:
1. There is no way to provide a comment for these code.
2. Later also, the code applied to a tk-window is cramped amongst
other properties for a particular window.
The only way to separate this code is by enclosing it within
curly-braces. Tcl's natural way to define code blocks. Unfortunatly this
also means to exclude local data from such a code block.
Example code-block:
create .tk.window -text test\
-command {
# the typical code fragment
do-something
} -background red
Using list in order to form substitutable code:
create .tk.window -text test\
-command [list do somthing $somevariable]\
-background red
The sequence for "" is similar to list --only a lot worse readable--
therefore i do ommit it here.
The list example has three significant aspects:
1. The code block gets cramped within the properties part of
the window creation.
2. The square brackets do suggest, that it is priortized executed
-- im writing about the logic, not the substitution.
3. There is no comment.
Now, i did replace some of my code, written with [list] and
converted it using subst.
The result in terms of readability had been tremendous.
Example (in our line of thought):
create .tk.window -text test\
-command [subst {
# a comment...
do somthing $somevariable
}] -background red
With subst it is possible to present the logic in 'Tcl's natural way'.
In a previous posting i did state:
'but limited to one line; more will make it as unreadable as using "".'
One line doesn't read one command, although it has been interpreted that
way. The point that all of us do write wrapper procedures, when multiple
commands are involved, steems from the limitations of [list] and "".
Wrapper procedures are a countermeasure against this limitations.
The last discourse did dwell on list's immunity against abuse.
Subst does not provide these sort of immunity. However, using curly
braces does provide the possibility to treat substitutions as atoms.
The same kind of immunity ([list]) can be reached by either writing
a new command: inoculatedSubst or by extending subst with an
attribute -inoculate.
-roger
No, most if us use procedures instead of a block of code to improve
maintainability. If I have a chunk of code that needs some variables
substituted when the widget is built and some at execution time, that
is trivial to do - pass the immediate substituted values in as args to
the procedure.
It also makes it much easier to provide multiple ways to do the same
thing (i.e. a button on a panel, or a menu item) - easy to call the same
proc instead of repeating blocks of code. Similarly it is easy to
add automation or test harnesses if the functionality of your code
doesn't directly rely on the GUI or it's elements
It also improves readability and maintainability (IMHO) by separating
code that is constructing the GUI from code that is performing a task.
Bruce
Arndt Roger Schneider wrote:
>> Hmm... TCL thinks otherwise...
>>
>> set happyMoustache ":-\{)"
>> set sadMoustache ":-\{("
>> button .$happyMoustache -text $happyMoustache -command \
>> [list .$happyMoustache configure -bg green]
>> button .$sadMoustache -text $sadMoustache -command \
>> [subst {{.$sadMoustache} configure -bg red}]
>> pack .$happyMoustache .$sadMoustache
>>
>> Works just fine for me, except that pushing the sad mustachioed face
>> produces an error, perhaps that's why he's sad... It certainly has
>> everything to do with lists though. Because if you then do:
>>
>> .$sadMoustache configure -command \
>> [list .$sadMoustache configure -bg red]
>>
>> It works.
> You are right tcl can source it.
>
>> It is an argument for exactly the reason you give: If you are unable
>> to predict the future, is it wiser to use the construct that is
>> guaranteed to work, or the one that might break? Obviously if you can
>> see the future perfectly, and know that no-one will ever use your code
>> in an odd way, then the unsafe method *MIGHT* be ok... But you can't,
>> so it is a good idea to do it right, and doing it right involves using
>> list.
>
>
>
> The worst kind of errors are those which go undetected.
> Using curly braces within window names is such an error -- i think you
> will agree with me.
I agree that errors that go undetected are bad, I don't agree that using
curly braces in a window name is such an error. I'm not convinced that
using characters other than alphanumerics, dashes and underscores in
window names is sensible, but it isn't (with one exception) an error.
>
>
> Tk has been written for the X11 environment, therefore
> the X11 documentation may serve as reference (excerpt from LocalDB):
While TK initially targetted at X11, it is now a cross platform window
system. Regardless, I see little or no relevance to quotes about the
locale database.
>
> X Locale Database only accepts XPCS, the X Portable Character Set. The
> reserved symbols are; the quotation mark("), the number sign (#), the
> semicolon(;), the backslash(\), the left brace({) and the right brace(}).
>
> ...
>
> www.x.org/X11R6.8.1/docs/i18n/LocaleDB.pdf
>
> Unfortunatly the document does not exclude spaces from being used within
> window names (instances), but the Xlib Programming Manual states on page
> 454:
>
> ... a name is often made up of multiple words, concatenated without
> spaces, ...
>
>
> Although X11 does not disallow using spaces wthin window names, in Tk it
> is an error. If you specify a resource, inside a resource file, for a
> name with a space in it, it will not being added to the option database
> , when using option readfile <resource file>.
You are again mistaken, it is not an error to use spaces in window
names, and never has been. If it is indeed not possible to specify
resources for such windows, than that is a bug in "option readfile", but
given the accuracy of your previous assertions I will wait to have such
a bug confirmed.
>
> In essence all presented examples against subst are errors themself,
> which may remain uncovered when using the the list idiom!
>
None of the presented examples are in fact errors, and hence are not
hidden by the use of [list]. Such usage is also not an "idiom", it is
canonical. Code that uses [subst] in the ways you have suggested will
exhibit bugs when presented with "strange" window names (and indeed
"strange" arguments), but that is because you should be using [list]
and/or a [proc] rather than [subst].
>>> You agreed --fine.
>>>
>>> -roger
>>>
>> I'm not sure he did agree. Just in case, the simple rules are:
>> 1) Use list to build the command.
>> 2) If you need more than one command, wrap it in a proc, and use list
>> to build the call to the proc.
>>
>> The complex rule is:
>> 1) Follow the simple rules.
>>
>> And now it's time for more painkillers and to return under my warm and
>> cozy rock...
>>
>> Dan "Surf by Corrections" Smart
>
>
> Well you do agree, too -- again fine.
No I most definitely do not agree.
>
> If you really want to use something like:
> -command "[list command1 $foo $bar] ; [list command2 $foo $bar]"
You almost certainly don't want to use that, and if you really really
do, then do not use [subst].
> then at last use subst:
>
Why?
What do you see as the advantages?
Did you try the code you suggested?
Do you know why it doesn't work?
> subst -novariables {
> [list command1 $foo $bar];
> [list command2 $foo $bar]
> }
>
>
> i guess we are through now?
>
I don't know if we are through, I'm going to continue to correct
mis-information whenever I'm able to (pain-killers etc not-withstanding).
>
> have a nice day
>
>
> -roger
Best Wishes
Dan "Ouch-bleepity-bleepity-bleep" Smart
I'd actually say that it is a misfeature of the Xrdb format, which was
never specified by JohnO (it's an X11 thing). You can always use the
[option add] command to define resources for widgets with spaces in,
which is a much more Tcl/Tk-ish way:
option add "*example.hello world.text" "Hello World!"
Donal.
To save Dan (why are you on painkillers anyway?) a bit of typing (and
contradicting my own promise to E this T):
Again: using 'subst' _here_ will _fail_ if '$somevariable' contains
spaces or other special characters. It will call do-something
(assuming this is the real proc name, and not 'do' called with
'somthing' as first arg) with more arguments than the proc expects,
will execute arbitrary code, etc etc., all depending what really is in
'$somevariable'. Eg., set somevariable {[exit]} will exit the program
when the -command triggers. Worse cases are easily imagined.
While you could argue that _widget names_ should not contain spaces
(or other special characters), you certainly cannot assure that
'$somevariable' will never contain anything which will break your
above code.
| With subst it is possible to present the logic in 'Tcl's natural
| way'.
No. The natural TCL way is to define a proc for anything like this,
and using 'list' to call the proc.
| The point that all of us do write wrapper procedures, when multiple
| commands are involved, steems from the limitations of [list] and "".
A plain `no, you're wrong here'.
| The list example has three significant aspects:
--<snip-snip>--
| 3. There is no comment.
If you need a comment, think about renaming the proc so that you don't
need a comment.
R', this is getting fun....
with option add, yes.
> I'd actually say that it is a misfeature of the Xrdb format, which was
> never specified by JohnO (it's an X11 thing). You can always use the
> [option add] command to define resources for widgets with spaces in,
> which is a much more Tcl/Tk-ish way:
>
> option add "*example.hello world.text" "Hello World!"
>
> Donal.
The X11 document doesn't state that spaces in window names are
forbidden, which i did point out.
-roger
Arndt Roger Schneider writes:
> The point that all of us do write wrapper procedures, when multiple
> commands are involved, steems from the limitations of [list] and "".
May I ask, what you see as the difference between "" and [subst]?
Functionally these two are the same, right? IOW both give the same
(bad) results.
% set x "a b c"
a b c
% puts "$x"
a b c
% puts [subst {$x}]
a b c
% puts [list $x]
{a b c}
%
benny
> May I ask, what you see as the difference between "" and [subst]?
> Functionally these two are the same, right? IOW both give the same
> (bad) results.
>
> % set x "a b c"
> a b c
> % puts "$x"
> a b c
> % puts [subst {$x}]
> a b c
> % puts [list $x]
> {a b c}
> %
I guess the only case is when used with -nocommands, as
puts [subst -nocommands {[exit]}]
would suggest. Just a thought. Also, -nobackslashes is another case. This
to point the difference between [subst] and "".
--
-Kaitzschu
s="TCL ";while true;do echo -en "\r$s";s=${s:1:${#s}}${s:0:1};sleep .1;done
Other people like [subst] far more than I do.
Donal.
Which is all rather beside the point IMO. The Xrdb format is crufty
anyway, and beside that doesn't support rich characters nicely. Give me
Tcl/Tk any day!
Donal.
Not quite. 'subst' allows for a second round of controlled
substitution. Assume:
set a A
set b B
set x {$a[$b]}
puts $x
=> $a[$b]
The -nobackslashes, -nocommand and -novariables flags of subst control
what should get substituted:
puts [subst $x]
error: invalid command name "B"
puts [subst -nocommands $x]
=> A[B]
In contrast, 'eval' just substitutes everything:
eval puts \"$x\"
error: invalid command name "B"
and '[set]' is limited to one variable:
puts [set $x]
error: can't read "$a[$b]": no such variable
| IOW both give the same (bad) results.
It depends on what you want to achieve. If you need a proper list, as
in -command arguments, subst is a bad choice, you should use 'list'
there. But for arbitrary controlled _string_ substitution, 'subst'
might be the Right Thing [TM].
R'
Had the same problem, searching through the X11 doc.:-)
xrdb isn't the only curfty X11 part.
-roger
I think i can finalize the discourse about subst.
Command substitution with list achives predictable code;
command substitution with subst don't.
The reasons why subst fails are:
1. a substitute may break into multiple terms,
this breakup can be countered by enclosing the substitute in
curly braces.
2. Tokens, which can only be formulated with backslashes in Tcl,
will change their meaning enclosed within curly braces.
The following is required when using a subst-like semantic for command
substitution:
If necessary, the substitute must be enclosed within curly braces.
If backslashes are required: enclosing qoutas must be used and
backslashes injected into the substitute.
-roger
No, that is not guaranteed to "counter" the "break into multiple terms".
It will for some cases but not for all.
> ...
> If necessary, the substitute must be enclosed within curly braces.
> If backslashes are required: enclosing qoutas must be used and
> backslashes injected into the substitute.
That all sounds so complicated.
How about "always use [list ...] to build up a command, and never
include more than one command in a string unless the second command is
"break"? That seems much easier to remember.
Another good rule of thumb, IMO, is "never use subst unless there is no
alternative". subst is useful for specific types of problems but
shouldn't be used as a general purpose mechanism.
No, only both countermeasurs would suffice.
>> ...
>> If necessary, the substitute must be enclosed within curly braces.
>> If backslashes are required: enclosing qoutas must be used and
>> backslashes injected into the substitute.
>
>
> That all sounds so complicated.
It is complicated.
> How about "always use [list ...] to build up a command, and never
> include more than one command in a string unless the second command is
> "break"? That seems much easier to remember.
>
> Another good rule of thumb, IMO, is "never use subst unless there is no
> alternative". subst is useful for specific types of problems but
> shouldn't be used as a general purpose mechanism.
>
Which will lead to the initial problems with subst in those special cases.
-roger
>> How about "always use [list ...] to build up a command, and never
>> include more than one command in a string unless the second command is
>> "break"? That seems much easier to remember.
>>
>> Another good rule of thumb, IMO, is "never use subst unless there is
>> no alternative". subst is useful for specific types of problems but
>> shouldn't be used as a general purpose mechanism.
>>
>
> Which will lead to the initial problems with subst in those special cases.
I guess I didn't make myself clear. My position is that one should never
use subst to build up a command, whether for a binding or a value for a
"-command" option. There are *always* alternatives IMO. Thus, never use
subst == never having problems with subst :-)
There are uses for subst, such as doing macro-like expansion in blocks
of text, but I would never advocate the use of subst for building up
commands.
I see Ramon mentioned this option but referred to it as 'normally not
advised'.
I haven't had a problem with it so far - but am I setting myself up for
the same sort of problems as subst?
It seems a pity to me that there isn't a generally applicable idiom for
building up a script like this safely.
Julian Noble.
'Subst' itself does not fail. What fails is interpreting the
resulting _string_ as a _list_, which is implicitly done by the 'eval'
applied to the -command.
You can try to get around this failure by introducing all kind of
quoting and bracing and what not, and will simply end up duplicating
what 'list' already does properly (if you get it right in the first
place).
R'
I see this option perfectly safe. The only problem to avoid,
as always in pattern matching, is to be sure that the pattern to
replace is not used in another part of the script.
If you use a pattern like %v1% it is quite easy to check visually
that the pattern is not used in the rest of the script. In this case,
you are safe because one substitution does not depend on other
substitutions, due to the nature of string map.
Be careful because in your code:
thread::send $tid [string map [list %v1% [list $v1] %v2% $v2] {}
$v2 should be [list $v2]
The reason of not recommending it is that there are easier ways
for the beginners in order to acomplish the most common tasks. This
is a sort of advanced feature for advanced requirements.
Regards,
Ramon Ribó
En Thu, 17 Nov 2005 01:40:10 +0100, neuro...@gmail.com
<neuro...@gmail.com> escribió:
--