Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How can I pass variable throught "-command"

12 views
Skip to first unread message

Hans

unread,
Nov 10, 2005, 4:40:25 PM11/10/05
to
Hi,

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

Gerald W. Lester

unread,
Nov 10, 2005, 4:52:24 PM11/10/05
to
Hans wrote:
>...

> text $cur_win1.txt2 -height 5 -yscrollcommand {$cur_win1.sb1 set}
> scrollbar $cur_win1.sb1 -command {$cur_win1.txt2 yview}
>...

> 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

unread,
Nov 10, 2005, 5:42:19 PM11/10/05
to
remember (or learn) TCLs quoting rules. When you use { }
to quote items NO substitution is done so you are passing
the literal string $cur_win1 if you use " " then the
variable will be substituted (or depending on what items
are in the command the [list ] command can be used for
safe handling of variables with spaces.

Bruce

sleb...@gmail.com

unread,
Nov 10, 2005, 9:04:22 PM11/10/05
to

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.

Ralf Fassel

unread,
Nov 11, 2005, 5:13:09 AM11/11/05
to
* "Gerald W. Lester" <Gerald...@cox.net>
| scrollbar $cur_win1.sb1 -command [$cur_win1.txt2 yview]

Ob-Nitpick:


scrollbar $cur_win1.sb1 -command [list $cur_win1.txt2 yview]

R'

Ralf Fassel

unread,
Nov 11, 2005, 5:15:44 AM11/11/05
to
* "sleb...@yahoo.com" <sleb...@gmail.com>

| 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.

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'

Donal K. Fellows

unread,
Nov 11, 2005, 5:25:49 AM11/11/05
to
sleb...@yahoo.com wrote:
> 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.

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.

Arndt Roger Schneider

unread,
Nov 11, 2005, 9:43:26 AM11/11/05
to
Donal K. Fellows schrieb:

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

Donal K. Fellows

unread,
Nov 11, 2005, 11:01:02 AM11/11/05
to
Arndt Roger Schneider wrote:
> 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]

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.

Bryan Oakley

unread,
Nov 11, 2005, 11:53:02 AM11/11/05
to
Arndt Roger Schneider wrote:
> 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 "".

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.

Cameron Laird

unread,
Nov 11, 2005, 12:08:04 PM11/11/05
to
In article <ygahdaj...@panther.akutech-local.de>,

? 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.

Ralf Fassel

unread,
Nov 11, 2005, 12:13:42 PM11/11/05
to
* Arndt Roger Schneider <roger.s...@addcom.de>

| i've used both; right-now i do prefer subst:
|
| scrollbar $cur_win1.sb1 -command [subst {$cur_win1.txt2 yview}]

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'

Gerald W. Lester

unread,
Nov 11, 2005, 2:56:16 PM11/11/05
to

Of course it was a typo!

Donal K. Fellows

unread,
Nov 11, 2005, 6:56:46 PM11/11/05
to
Ralf Fassel wrote:
> Pray that nobody names their widgets
> set cur_win1 {.foo [exec rm -f $::env(HOME)]}

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.

Ralf Fassel

unread,
Nov 12, 2005, 9:32:15 AM11/12/05
to
* "Donal K. Fellows" <donal.k...@manchester.ac.uk>

| > set cur_win1 {.foo [exec rm -f $::env(HOME)]}
|
| 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 ~/.]}

*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.

Arndt Roger Schneider

unread,
Nov 12, 2005, 10:07:05 AM11/12/05
to
Ralf Fassel schrieb:

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


Ralf Fassel

unread,
Nov 12, 2005, 11:45:13 AM11/12/05
to
* Arndt Roger Schneider <roger.s...@addcom.de>
| scrollbar $cur_win1.sb1 -command [subst {{$cur_win1.txt2} yview}]

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'

Arndt Roger Schneider

unread,
Nov 12, 2005, 12:26:54 PM11/12/05
to
Ralf Fassel schrieb:

> * Arndt Roger Schneider <roger.s...@addcom.de>
> | scrollbar $cur_win1.sb1 -command [subst {{$cur_win1.txt2} yview}]
>
> Same problem, just use a curly in the cur_win1 name, gives you an
> 'unmatched paren' error when the scrollbar is invoked.

... 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


Dan Smart

unread,
Nov 12, 2005, 3:07:29 PM11/12/05
to
Arndt Roger Schneider wrote:
> Ralf Fassel schrieb:
>
>> * Arndt Roger Schneider <roger.s...@addcom.de>
>> | scrollbar $cur_win1.sb1 -command [subst {{$cur_win1.txt2} yview}]
>>
>> Same problem, just use a curly in the cur_win1 name, gives you an
>> 'unmatched paren' error when the scrollbar is invoked.
>
>
> ... tcl can't source such a script (unmatched curly braces), has nothing
> to do with list or substitutions.
>
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 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

Arndt Roger Schneider

unread,
Nov 13, 2005, 8:27:05 AM11/13/05
to
Dan Smart schrieb:

> Arndt Roger Schneider wrote:
>
>> Ralf Fassel schrieb:
>>
>>> * Arndt Roger Schneider <roger.s...@addcom.de>
>>> | scrollbar $cur_win1.sb1 -command [subst {{$cur_win1.txt2} yview}]
>>>
>>> Same problem, just use a curly in the cur_win1 name, gives you an
>>> 'unmatched paren' error when the scrollbar is invoked.
>>
>>
>>
>> ... tcl can't source such a script (unmatched curly braces), has
>> nothing to do with list or substitutions.
>>
> 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.


>
>>
>>> 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

Bryan Oakley

unread,
Nov 13, 2005, 9:48:09 AM11/13/05
to
Arndt Roger Schneider wrote:

> 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...)

Ramon Ribó

unread,
Nov 13, 2005, 12:40:35 PM11/13/05
to

Hello,

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:

http://wiki.tcl.tk/9330

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

John Seal

unread,
Nov 14, 2005, 7:31:58 AM11/14/05
to
Donal K. Fellows wrote:

> Remember, in robust software engineering it is paranoia that wins!

QOTW-worthy wisdom.

Gerald W. Lester

unread,
Nov 14, 2005, 9:42:37 AM11/14/05
to

If it is going to be more than **one** ***short*** line -- than write a
procedure and call the procedure with parameters!!!

Arndt Roger Schneider

unread,
Nov 14, 2005, 11:45:18 AM11/14/05
to
Bryan Oakley wrote:

[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

Arndt Roger Schneider

unread,
Nov 14, 2005, 12:51:18 PM11/14/05
to

Initial i did state that i have used list aswell as "" in order to form
dynamic code blocks.


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

Bruce

unread,
Nov 14, 2005, 3:28:36 PM11/14/05
to
Arndt Roger Schneider wrote:
>
> 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.

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

Dan Smart

unread,
Nov 14, 2005, 5:44:36 PM11/14/05
to
What follows is mostly dictated and then manually editted, odds are it
will suffer from the worst failings of both.

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

Donal K. Fellows

unread,
Nov 15, 2005, 4:21:01 AM11/15/05
to
Dan Smart wrote:
> 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.

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.

Ralf Fassel

unread,
Nov 15, 2005, 6:21:54 AM11/15/05
to
* Arndt Roger Schneider <roger.s...@addcom.de>
| 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

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....

Arndt Roger Schneider

unread,
Nov 15, 2005, 8:14:24 AM11/15/05
to
Donal K. Fellows schrieb:

> Dan Smart wrote:
>
>> 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.


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

Benjamin Riefenstahl

unread,
Nov 15, 2005, 2:35:07 PM11/15/05
to
Hi 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

Kaitzschu

unread,
Nov 15, 2005, 2:59:09 PM11/15/05
to
On Tue, 15 Nov 2005, Benjamin Riefenstahl wrote:

> 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

Donal K. Fellows

unread,
Nov 15, 2005, 6:38:52 PM11/15/05
to
You use [subst] when you want the point where the things are
substituted to be different from the place where you write the string
down. It's useful for templating systems. I hardly ever use it (and
once I get around to making [regsub] do "command substitutions" in some
suitable sense, that'll drop to zero for me).

Other people like [subst] far more than I do.

Donal.

Donal K. Fellows

unread,
Nov 15, 2005, 6:46:46 PM11/15/05
to
Well, I've not been able to find a full description of the quoting
rules in a quick search of my X11 docs. But a few examples that I found
seem to indicate that it is colon which is forbidden in some sense.

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.

Ralf Fassel

unread,
Nov 16, 2005, 4:30:20 AM11/16/05
to
* Benjamin Riefenstahl <b.rief...@turtle-trading.net>

| May I ask, what you see as the difference between "" and [subst]?
| Functionally these two are the same, right?

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'

Arndt Roger Schneider

unread,
Nov 16, 2005, 10:10:37 AM11/16/05
to
Donal K. Fellows schrieb:

Had the same problem, searching through the X11 doc.:-)
xrdb isn't the only curfty X11 part.

-roger

Arndt Roger Schneider

unread,
Nov 16, 2005, 10:37:11 AM11/16/05
to
Hi,

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

Bryan Oakley

unread,
Nov 16, 2005, 10:50:44 AM11/16/05
to
Arndt Roger Schneider wrote:
> 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.

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.

Arndt Roger Schneider

unread,
Nov 16, 2005, 11:45:05 AM11/16/05
to
Bryan Oakley schrieb:

> Arndt Roger Schneider wrote:
>
>> 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.
>
>
> No, that is not guaranteed to "counter" the "break into multiple terms".
> It will for some cases but not for all.

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

Bryan Oakley

unread,
Nov 16, 2005, 1:24:33 PM11/16/05
to
Arndt Roger Schneider wrote:

>> 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.

neuro...@gmail.com

unread,
Nov 16, 2005, 7:40:10 PM11/16/05
to
While for -command cases I also tend to use [list ..] and a helper proc
- there are other situations that require local data to be substituted
in a script, but where this approach isn't appropriate. I'm thinking
particularly of:
thread::send $tid {
do something
}
Clearly a helper proc wouldn't necessarily be available in the
receiving thread.
Such a helper could be made available easily enough by for example
putting it in a package - but often the logical and most maintainable
place for the script is in the source thread.
I usually do something like:
thread::send $tid [string map [list %v1% [list $v1] %v2% $v2] {
do something %v1% %v2%
etc
}]
Where I think of %v2% as in a sense being auto {expand}ed because $v2
isn't protected by an additional [list..] in the mapping.

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.

Ralf Fassel

unread,
Nov 17, 2005, 2:59:21 AM11/17/05
to
* Arndt Roger Schneider <roger.s...@addcom.de>
| Command substitution with list achives predictable code;
| command substitution with subst don't.
|
| The reasons why subst fails are:

'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'

Ramon Ribó

unread,
Nov 17, 2005, 6:24:00 AM11/17/05
to

Hello,

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ó:

--

0 new messages