From: Andreas Leitgeb on
Keith <kilowattradio(a)use-reply-to.invalid> wrote:
>> On 09 Apr 2010 15:11:27 GMT, Andreas Leitgeb
>> <avl(a)gamma.logic.tuwien.ac.at> wrote in
>> [ comp.lang.tcl ]:
>> > If you use tcl8.5 or higher, use:
>> > {exec {*}$browser "http://web.com/Pr...?sortcol=table;up=#Pr..." &}
>> > No need for eval here, unless the contents of $browser really need
>> > another round of full substitution...
>> Ok what does the {*} do in eval?
> I mean in exec.

It's a new syntax feature of tcl8.5

It causes the following value (the value stored in variable browser
in your case) to be taken as a list and expanded into a number of
separate arguments.

Likely, your $browser is a list consisting of your browsers actual
command name, and some options that tell it to use the next argument
as an URL to open.

Before this syntax was added, the command "eval" was used for this
task, but that had the intended, but often unwanted effect of not
only expanding one specific argument, but rather to expand and
re-interpret *all* of its arguments - thus the URL in your case.

There were also idioms to effectively prevent this, namely wrapping
the other arguments (those, that one didn't want to expand) into
[list ...]-commands, but those were so clumsy and easily forgotten,
that for 8.5 (after very long discussions here) finally this new
syntax was agreed upon.

From: Mark Janssen on
On Apr 9, 4:02 pm, Keith <kilowattra...(a)use-reply-to.invalid> wrote:
> ttk::button $t.h.0 -text "Programming Locations Manual Web Page"
> -command \
> {eval exec $browser \
> "http://web.com/Programming?sortcol=table\x3Bup=\x23Programming_general_locations"
> \
>  &}
>
> I have tried the above command also with:
> "http://web.com/Programming?sortcol=table\;up=\#Programming_general_locations"
>
> but each time tcl reads the ; and creates an error. var $browser can
> change with each users prefernces so I can't change that in the command.
>
> How do I get tcl to eval the command without interpreting the ; and
> creating the error?
>
> TIA,
>
> Keith
>
> --
> Best Regards, Keithhttp://home.comcast.net/~kilowattradio/
> I'm Your Huckle Berryhttp://www.youtube.com/watch?v=KfbAFgD2mLo

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.

Mark
From: tom.rmadilo on
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,
in fact, expand could cause just as much trouble as either [eval] or
[exec].

Callbacks should, when possible, get boiled down to simple command
invocations...if for no other reason that a callback might be called
back from more than one point, so if the callback isn't a command you
have duplicate script code which takes up space, is hard to understand
and hard to maintain.
From: Donal K. Fellows on
On 9 Apr, 22:36, "tom.rmadilo" <tom.rmad...(a)gmail.com> wrote:
> This sounds like very good advice. Although I appreciate the utility
> of expand, ( {*} ), expand simply cannot be the answer to this issue,
> in fact, expand could cause just as much trouble as either [eval] or
> [exec].

No, since it uses list syntax for parsing the value to substitute, and
not command syntax. In lists, semicolons are not special and nor are
the vast majority of other Tcl metasyntax characters. Moreover, the
substituted values are not resubstituted after parsing; it's behaviour
is very predictable. (In short, I'm certain we got the semantics of
expansion correct, and the syntax... well, I've given up fighting
there.)

> Callbacks should, when possible, get boiled down to simple command
> invocations...if for no other reason that a callback might be called
> back from more than one point, so if the callback isn't a command you
> have duplicate script code which takes up space, is hard to understand
> and hard to maintain.

The points about comprehension and maintenance are good. Any time I've
written a non-local callback without a procedure to mediate it (or an
[apply] term) I've regretted it on the above grounds. (I exclude
"local" callbacks, such as custom looping commands, [foreach] bodies,
[namespace eval] calls, etc. They're also callbacks in a sense, but
they're "tame".) Oh, callbacks to methods of objects work well too,
but then they're another largely procedure-like entity. :-)

Donal.
From: tom.rmadilo on
On Apr 9, 3:10 pm, "Donal K. Fellows"
<donal.k.fell...(a)manchester.ac.uk> wrote:
> On 9 Apr, 22:36, "tom.rmadilo" <tom.rmad...(a)gmail.com> wrote:
>
> > This sounds like very good advice. Although I appreciate the utility
> > of expand, ( {*} ), expand simply cannot be the answer to this issue,
> > in fact, expand could cause just as much trouble as either [eval] or
> > [exec].
>
> No, since it uses list syntax for parsing the value to substitute, and
> not command syntax. In lists, semicolons are not special and nor are
> the vast majority of other Tcl metasyntax characters. Moreover, the
> substituted values are not resubstituted after parsing; it's behaviour
> is very predictable. (In short, I'm certain we got the semantics of
> expansion correct, and the syntax... well, I've given up fighting
> there.)

I think you are better at making exact arguments than I am, but what I
meant to say is that expand interprets what follows as a list (but the
syntax could be screwed up somewhere). Usually [expr] and [eval] work
great, but this still depends on the parsed syntax. Screw-ups happen
when you try to recurse list/command syntax and quoting rules.

But expand still solves a difficult issue, it is something like an
adapter syntax. In general, it would be better to eliminate command
syntax which uses a series of args instead of a formal list of
containing the args, but this isn't always possible.

Expand is kind of like democracy: very ugly, but less ugly than any
other option.

> > Callbacks should, when possible, get boiled down to simple command
> > invocations...if for no other reason that a callback might be called
> > back from more than one point, so if the callback isn't a command you
> > have duplicate script code which takes up space, is hard to understand
> > and hard to maintain.
>
> The points about comprehension and maintenance are good. Any time I've
> written a non-local callback without a procedure to mediate it (or an
> [apply] term) I've regretted it on the above grounds. (I exclude
> "local" callbacks, such as custom looping commands, [foreach] bodies,
> [namespace eval] calls, etc. They're also callbacks in a sense, but
> they're "tame".) Oh, callbacks to methods of objects work well too,
> but then they're another largely procedure-like entity. :-)

Of course, a method could potentially be more generic than a typical
procedure call. All that has to match is the call signature. The code
executed could differ. The important point is that the user code uses
a generic callback interface. Instead of object methods, I usually use
a variable to hold the procedure name for a generic procedure. They
seem practically the same to me.