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

Using parameters in a catch

57 views
Skip to first unread message

Cecil Westerhof

unread,
Apr 27, 2018, 4:44:04 AM4/27/18
to
I like to do something like:
set parameters "list --no-cache-dir --outdated"

while {[catch {set output [exec ${pip} ${parameters}]} errorStr opts]} {

The variable pip contains pip2, or pip3.

But when I do this I get:
ERROR: unknown command "list --no-cache-dir --outdated"

What do I need to change to make it work?


I could change it to:
while {[catch {set output [exec ${pip} list --no-cache-dir --outdated]} \
errorStr opts]} {

But I would prefer not to. One reason: the parameters will change.

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

stefan

unread,
Apr 27, 2018, 5:06:38 AM4/27/18
to

> What do I need to change to make it work?

use the expansion operator {*}:

while {[catch {set output [exec ${pip} {*}${parameters}]} errorStr opts]}

hth,
stefan

Cecil Westerhof

unread,
Apr 27, 2018, 7:44:05 AM4/27/18
to
That works like a charm. Thanks.


I think I add a page this weekend to make it easier to find this
solution.

Rich

unread,
Apr 27, 2018, 10:19:29 AM4/27/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> I like to do something like:
> set parameters "list --no-cache-dir --outdated"
>
> while {[catch {set output [exec ${pip} ${parameters}]} errorStr opts]} {
>
> The variable pip contains pip2, or pip3.
>
> But when I do this I get:
> ERROR: unknown command "list --no-cache-dir --outdated"
>
> What do I need to change to make it work?
>
>
> I could change it to:
> while {[catch {set output [exec ${pip} list --no-cache-dir --outdated]} \
> errorStr opts]} {
>
> But I would prefer not to. One reason: the parameters will change.
>

As stefan has pointed out, you want the expansion operator {*}.

But, you also want to use the Tcl [list] command to build the list that
you eventually pass to the expansion operator:

set parameters [list list --no-cache-dir --outdated]

You'll avoid subtle, data content dependent, errors later if you do
this small change now.

The reason is that {*} expects a list, and if the variable it is
'expanding' is not a list, then Tcl will attempt to convert it to a
list at runtime.

But, if at that later runtime the string's been modified such that it
will not implicitly parse into a list, you'll get an oddball error that
was never there before, and that seems to depend upon random phases of
the moon (until you finally track down the root cause). And all with
code that has not changed for a long time (making it harder to find the
root cause).


Donal K. Fellows

unread,
Apr 30, 2018, 7:05:54 AM4/30/18
to
On 27/04/2018 09:35, Cecil Westerhof wrote:
> But I would prefer not to. One reason: the parameters will change.

Those are *good* instincts! Others have told you what's wrong; I'm just
building on what they've said.

One thing I often like to do where I've got a fairly complex command
being called from Tcl is to make a little procedure that wraps it to
handle the actual calling, any packing of arguments, and ensuring that
the output is parsed correctly. (In some cases, you need to use some
non-obvious redirects to make things work, or tricky shell
intermediates. That's pretty horrible, and a great reason for hiding the
details.) In this case, it might be as simple as:

proc pip args {
global pip
exec $pip {*}$args
}


while {[catch {set output [pip {*}$parameters]} errStr opts]} {
....
}

Or you might push more smartness into the procedure. (For example, some
commands _insist_ on exiting with non-zero result codes even for trivial
issues, and you have to filter such things out and do special tricks to
get the output from them in such cases.)

Donal.
--
Donal Fellows — Tcl user, Tcl maintainer, TIP editor.
0 new messages