• Why do we need "eval"? (Expect question)

    From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Thu Sep 12 15:07:41 2024
    From Newsgroup: comp.lang.tcl

    Consider this (Unix/Linux/bash) command line:

    $ expect -- /dev/fd/3 3<<< 'eval spawn -noecho printf {{\t%s\n}} $argv;interact' $(seq 1 10)

    This correctly generates the output (each line starts with a tab):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    But notice how we have to use "eval" in order to split up the args in $argv. And, since we are using "eval", we have to "double quote" (with {}) the "format" arg to "printf". It'd be nice if neither of these things were necessary.

    I've always believed that "eval" was "evil" and to be avoided if at all possible - both in shell and in Tcl. It has strange side effects, such as
    we see here (the need to "double quote"). Is there any way to get the
    above effect w/o using "eval" ?
    --
    "Every time Mitt opens his mouth, a swing state gets its wings."

    (Should be on a bumper sticker)
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Thu Sep 12 19:33:01 2024
    From Newsgroup: comp.lang.tcl

    Am 12.09.2024 um 17:07 schrieb Kenny McCormack:
    Consider this (Unix/Linux/bash) command line:

    $ expect -- /dev/fd/3 3<<< 'eval spawn -noecho printf {{\t%s\n}} $argv;interact' $(seq 1 10)

    This correctly generates the output (each line starts with a tab):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    But notice how we have to use "eval" in order to split up the args in $argv. And, since we are using "eval", we have to "double quote" (with {}) the "format" arg to "printf". It'd be nice if neither of these things were necessary.

    I've always believed that "eval" was "evil" and to be avoided if at all possible - both in shell and in Tcl. It has strange side effects, such as
    we see here (the need to "double quote"). Is there any way to get the
    above effect w/o using "eval" ?


    Kenny,
    thanks for the question. Here is the answer by a TCL'er without expect knowledge.

    "eval" does an additional round of substitutions. This happens for all elements and is intended, if a whole command is included in a variable.

    To only expand some arguments, the list expansion operator may be used:

    In your case:
    eval spawn -noecho printf {{\t%s\n}} $argv
    equal to:
    spawn -noecho printf {\t%s\n} {*}$argv
    eventually, this works to:
    spawn -noecho printf \t%s\n {*}$argv

    Harald


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Thu Sep 12 18:45:30 2024
    From Newsgroup: comp.lang.tcl

    In article <vbv8kd$blsb$1@dont-email.me>,
    Harald Oehlmann <wortkarg3@yahoo.com> wrote:
    Am 12.09.2024 um 17:07 schrieb Kenny McCormack:
    Consider this (Unix/Linux/bash) command line:

    $ expect -- /dev/fd/3 3<<< 'eval spawn -noecho printf {{\t%s\n}} >$argv;interact' $(seq 1 10)

    This correctly generates the output (each line starts with a tab):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    But notice how we have to use "eval" in order to split up the args in $argv. >> And, since we are using "eval", we have to "double quote" (with {}) the
    "format" arg to "printf". It'd be nice if neither of these things were
    necessary.

    I've always believed that "eval" was "evil" and to be avoided if at all
    possible - both in shell and in Tcl. It has strange side effects, such as >> we see here (the need to "double quote"). Is there any way to get the
    above effect w/o using "eval" ?

    ...
    To only expand some arguments, the list expansion operator may be used:

    In your case:
    eval spawn -noecho printf {{\t%s\n}} $argv
    equal to:
    spawn -noecho printf {\t%s\n} {*}$argv
    eventually, this works to:
    spawn -noecho printf \t%s\n {*}$argv

    Indeed it does. Thanks! This solves my issue.

    ISTM that this {*} thing is a relatively recent addition to the langauge,
    since Expect has been around for a long time, and most of the scripts that
    do this sort of thing were written long ago.
    --
    person woman man camera tv
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Rich@rich@example.invalid to comp.lang.tcl on Fri Sep 13 04:32:55 2024
    From Newsgroup: comp.lang.tcl

    Kenny McCormack <gazelle@shell.xmission.com> wrote:
    ISTM that this {*} thing is a relatively recent addition to the langauge,

    Not really, it was added in 8.5, which was released Feb 12, 2016 [1]. Although 2016 *is* relatively recent in regards to many expect scripts.

    since Expect has been around for a long time, and most of the scripts that
    do this sort of thing were written long ago.

    Before 8.5, 'eval' was the way to perform the "splicing" that {*}
    provides.


    [1] https://www.tcl.tk/software/tcltk/8.5.tml
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Rich@rich@example.invalid to comp.lang.tcl on Fri Sep 13 04:36:04 2024
    From Newsgroup: comp.lang.tcl

    Harald Oehlmann <wortkarg3@yahoo.com> wrote:
    spawn -noecho printf {\t%s\n} {*}$argv
    eventually, this works to:
    spawn -noecho printf \t%s\n {*}$argv

    Do note that the second one causes \t and \n to be interpreted by Tcl's parser, so printf gets passed a literal tab and literal newline in its parameter list. The first passes the \ and t characters on to printf,
    and then printf does the interpretation.

    Both likely work fine for printf, but may not work fine for all
    possible external commands.

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Fri Sep 13 08:21:53 2024
    From Newsgroup: comp.lang.tcl

    Am 12.09.2024 um 20:45 schrieb Kenny McCormack:
    ISTM that this {*} thing is a relatively recent addition to the langauge, since Expect has been around for a long time, and most of the scripts that
    do this sort of thing were written long ago.

    "Relatively recent" is quite relative. Here is the relevant changes file entry:

    2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs)
    *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

    ;-)



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Fri Sep 13 08:47:39 2024
    From Newsgroup: comp.lang.tcl

    Am 13.09.2024 um 06:32 schrieb Rich:
    Kenny McCormack <gazelle@shell.xmission.com> wrote:
    ISTM that this {*} thing is a relatively recent addition to the langauge,

    Not really, it was added in 8.5, which was released Feb 12, 2016 [1]. Although 2016 *is* relatively recent in regards to many expect scripts.

    since Expect has been around for a long time, and most of the scripts that >> do this sort of thing were written long ago.

    Before 8.5, 'eval' was the way to perform the "splicing" that {*}
    provides.


    [1] https://www.tcl.tk/software/tcltk/8.5.tml

    Sorry, this date is TCL 8.5.19. The {*} was TCL 8.5.0...
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Fri Sep 13 11:21:07 2024
    From Newsgroup: comp.lang.tcl

    In article <vc0f9n$ml8n$1@dont-email.me>, Rich <rich@example.invalid> wrote: >Kenny McCormack <gazelle@shell.xmission.com> wrote:
    ISTM that this {*} thing is a relatively recent addition to the langauge,

    Not really, it was added in 8.5, which was released Feb 12, 2016 [1]. >Although 2016 *is* relatively recent in regards to many expect scripts.

    Well, yes, really, from the perspective of Expect.

    That was my point - that Expect hasn't really changed much since the late
    90s, and most of the active development was done then. The scripts that I
    have in mind - such as "unbuffer" - date back to that era.

    since Expect has been around for a long time, and most of the scripts that >> do this sort of thing were written long ago.

    Before 8.5, 'eval' was the way to perform the "splicing" that {*}
    provides.

    Right. OK.

    I'm glad I learned about {*}.
    --
    This is the GOP's problem. When you're at the beginning of the year
    and you've got nine Democrats running for the nomination, maybe one or
    two of them are Dennis Kucinich. When you have nine Republicans, seven
    or eight of them are Michelle Bachmann.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Fri Sep 13 11:26:10 2024
    From Newsgroup: comp.lang.tcl

    In article <vc0ffk$ml8n$2@dont-email.me>, Rich <rich@example.invalid> wrote: >Harald Oehlmann <wortkarg3@yahoo.com> wrote:
    spawn -noecho printf {\t%s\n} {*}$argv
    eventually, this works to:
    spawn -noecho printf \t%s\n {*}$argv

    Do note that the second one causes \t and \n to be interpreted by Tcl's >parser, so printf gets passed a literal tab and literal newline in its >parameter list. The first passes the \ and t characters on to printf,
    and then printf does the interpretation.

    Both likely work fine for printf, but may not work fine for all
    possible external commands.


    I think you misunderstand Harald's post (i.e., his notation).

    The point is that if you pass {{\t%s\n}} to "eval", both sets of braces get removed and what "printf" sees is (literally)

    backslash tee percent ess backslash en

    If you only pass a single level of braces, and eval it, then yes, as you
    said, printf will see

    tab percent ess newline
    --
    "Insisting on perfect safety is for people who don't have the balls to live
    in the real world."

    - Mary Shafer, NASA Ames Dryden -
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Fri Sep 13 17:17:46 2024
    From Newsgroup: comp.lang.tcl

    In article <vc0lm1$npv9$1@dont-email.me>,
    Harald Oehlmann <wortkarg3@yahoo.com> wrote:
    Am 12.09.2024 um 20:45 schrieb Kenny McCormack:
    ISTM that this {*} thing is a relatively recent addition to the langauge,
    since Expect has been around for a long time, and most of the scripts that >> do this sort of thing were written long ago.

    "Relatively recent" is quite relative. Here is the relevant changes file >entry:

    2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs)
    *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

    ;-)

    The other poster seemed to think 2016 (not 2006). That's still 8 years
    ago...
    --
    Republican Congressman Matt Gaetz claims that only ugly women want
    abortions, which they will never need since no one will impregnate them.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Rich@rich@example.invalid to comp.lang.tcl on Fri Sep 13 17:24:58 2024
    From Newsgroup: comp.lang.tcl

    Kenny McCormack <gazelle@shell.xmission.com> wrote:
    In article <vc0lm1$npv9$1@dont-email.me>,
    Harald Oehlmann <wortkarg3@yahoo.com> wrote:
    Am 12.09.2024 um 20:45 schrieb Kenny McCormack:
    ISTM that this {*} thing is a relatively recent addition to the langauge, >>> since Expect has been around for a long time, and most of the scripts that >>> do this sort of thing were written long ago.

    "Relatively recent" is quite relative. Here is the relevant changes file >>entry:

    2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs)
    *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

    ;-)

    The other poster seemed to think 2016 (not 2006). That's still 8 years ago...

    I pulled a date for a "point version" of 8.5 instead of 8.5.0.
    --- Synchronet 3.20a-Linux NewsLink 1.114