From: Andreas Leitgeb on
tom.rmadilo <tom.rmadilo(a)gmail.com> wrote:
> On Apr 9, 11:01 am, Mark Janssen <mpc.jans...(a)gmail.com> wrote:
>> There are several reason why using commands in callbacks is a good
>> idea. 'Quoting hell' is one of them. A simple proc like [open_url]
>> will do exactly the same with much less chance of screwing up the
>> quoting.
> This sounds like very good advice. Although I appreciate the utility
> of expand, ( {*} ), expand simply cannot be the answer to this issue,

It depends on what you refer to with "this issue".
If you mean the situation that Mark obviously meant, then yes, but
the OP's situation was slightly different.

OP's task (roughly):
button .b -command {eval exec $browser "http://x.y.z/;&#" &}

This whole callback does not depend on any local variables,
just one global one. ("Quoting hell" usually comes from blending
local variables into commands.) He could have made a procedure
of it:

proc openXYZ {} {
eval exec $::browser "http://x.y.z/;&#" &
}
button .b -command openXYZ

But that wouldn't have solved his problem in any way.

He also could have used a more generic procedure:

proc openURL {url} {
eval exec $::browser $url &
}
button .b -command {openURL "http://x.y.z/;&#"}
or:
button .b -command [list openURL "http://x.y.z/;&#"]

and once again, this separating out would have helped nothing at all
against his bad use of eval.

I agree that using procedures in such cases is a good idea,
but then the task is, what the procedure should rather look
like:

proc openXYZ {} {
exec {*}$::browser "http://x.y.z/;&#" &
}
or:
proc openURL {url} {
exec {*}$::browser $url &
}
or (up to tcl 8.4):
proc openURL {url} {
eval exec $::browser [list $url] &
}


> in fact, expand could cause just as much trouble as either [eval] or
> [exec].

That just doesn't make any sense to me. It's like saying "[list] could
cause just as much trouble as...", namely if it is applied at the wrong
spot.

From: tom.rmadilo on
On Apr 10, 1:20 am, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at>
wrote:
> tom.rmadilo <tom.rmad...(a)gmail.com> wrote:
> > On Apr 9, 11:01 am, Mark Janssen <mpc.jans...(a)gmail.com> wrote:
> >> There are several reason why using commands in callbacks is a good
> >> idea. 'Quoting hell' is one of them. A simple proc like [open_url]
> >> will do exactly the same with much less chance of screwing up the
> >> quoting.
> > This sounds like very good advice. Although I appreciate the utility
> > of expand, ( {*} ), expand simply cannot be the answer to this issue,
>
> It depends on what you refer to with "this issue".
> If you mean the situation that Mark obviously meant, then yes, but
> the OP's situation was slightly different.
>
> OP's task (roughly):
>   button .b -command {eval exec $browser "http://x.y.z/;&#" &}
>
> This whole callback does not depend on any local variables,
> just one global one. ("Quoting hell" usually comes from blending
> local variables into commands.)  He could have made a procedure
> of it:
>
> proc openXYZ {} {
>   eval exec $::browser "http://x.y.z/;&#" &}
>
> button .b -command openXYZ
>
> But that wouldn't have solved his problem in any way.
>
> He also could have used a more generic procedure:
>
> proc openURL {url} {
>   eval exec $::browser $url &}
>
> button .b -command {openURL "http://x.y.z/;&#"}
> or:
> button .b -command [list openURL "http://x.y.z/;&#"]
>
> and once again, this separating out would have helped nothing at all
> against his bad use of eval.
>
> I agree that using procedures in such cases is a good idea,
> but then the task is, what the procedure should rather look
> like:
>
> proc openXYZ {} {
>   exec {*}$::browser "http://x.y.z/;&#" &}
>
> or:
> proc openURL {url} {
>   exec {*}$::browser $url &}
>
> or (up to tcl 8.4):
> proc openURL {url} {
>   eval exec $::browser [list $url] &
>
> }
> > in fact, expand could cause just as much trouble as either [eval] or
> > [exec].
>
> That just doesn't make any sense to me. It's like saying "[list] could
> cause just as much trouble as...", namely if it is applied at the wrong
> spot.

The problem is using eval, which turns all the args into a single
string. For instance, this simple command also causes a problem:

% set url http://www.example.com/?x=y;a=b
invalid command name "a=b"

We just ran [eval] over the string http://www.example.com/?x=y;a=b,
which it broke into two commands, which it is.

From: Andreas Leitgeb on
tom.rmadilo <tom.rmadilo(a)gmail.com> wrote:
> Andreas Leitgeb wrote:
>> tom.rmadilo <tom.rmadilo(a)gmail.com> wrote:
>> > in fact, expand could cause just as much trouble as either [eval] or
>> > [exec].
>> That just doesn't make any sense to me.
>
> The problem is using eval, which turns all the args into a single
> string. For instance, this simple command also causes a problem:

Indeed. That's why your previous statement made no sense to me. Also,
the troubles possibly caused by bad use of [eval] and [exec] are so
completely different of nature, that naming them toghether is like
adding meters and kilograms.

From: tom.rmadilo on
On Apr 10, 1:46 pm, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at>
wrote:
> tom.rmadilo <tom.rmad...(a)gmail.com> wrote:
> > Andreas Leitgeb wrote:
> >> tom.rmadilo <tom.rmad...(a)gmail.com> wrote:
> >> > in fact, expand could cause just as much trouble as either [eval] or
> >> > [exec].
> >> That just doesn't make any sense to me.
>
> > The problem is using eval, which turns all the args into a single
> > string. For instance, this simple command also causes a problem:
>
> Indeed.  That's why your previous statement made no sense to me. Also,
> the troubles possibly caused by bad use of [eval] and [exec] are so
> completely different of nature, that naming them toghether is like
> adding meters and kilograms.

Let me start over, because there is nothing categorically wrong with
using eval and exec together, but eval creates a string, like using
[concat], exec becomes part of that string. Part of the discussion was
about removing scripts from callbacks and introducing a procedure
instead. So, a better callback would maybe look like this:

{openURL $url}

and openURL:

proc openURL { url } {
exec wget -S $url &
}

Where "wget -S" is directly used instead of being held in a variable
requiring the use of expand. Using eval on user supplied strings is
also very dangerous.

For instance, try:

% eval exec {wget -S} "http://www.example.com/?a=\[ls];b=c" &

compared to:

% openURL "http://www.example.com/?a=\[ls];b=c"
% openURL "http://www.example.com/?a=b;x=y"
% openURL "http://www.example.com/?a=b&x=y"