Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  nodelist  faq  login

A rolling disk gathers no MOS.


programming / comp.lang.tcl / Re: Why do I need to "join" it?

SubjectAuthor
* Why do I need to "join" it?Kenny McCormack
+* Re: Why do I need to "join" it?saitology9
|`* Re: Why do I need to "join" it?Kenny McCormack
| +- Re: Why do I need to "join" it?briang
| `- Re: Why do I need to "join" it?saitology9
+- Re: Why do I need to "join" it?mango
`- Re: Why do I need to "join" it?Ralf Fassel

1
Subject: Why do I need to "join" it?
From: Kenny McCormack
Newsgroups: comp.lang.tcl
Organization: The official candy of the new Millennium
Date: Sat, 14 May 2022 11:27 UTC
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!xmission!nnrp.xmission!.POSTED.shell.xmission.com!not-for-mail
From: gaze...@shell.xmission.com (Kenny McCormack)
Newsgroups: comp.lang.tcl
Subject: Why do I need to "join" it?
Date: Sat, 14 May 2022 11:27:23 -0000 (UTC)
Organization: The official candy of the new Millennium
Message-ID: <t5o3mr$71or$1@news.xmission.com>
Injection-Date: Sat, 14 May 2022 11:27:23 -0000 (UTC)
Injection-Info: news.xmission.com; posting-host="shell.xmission.com:166.70.8.4";
logging-data="231195"; mail-complaints-to="abuse@xmission.com"
X-Newsreader: trn 4.0-test77 (Sep 1, 2010)
Originator: gazelle@shell.xmission.com (Kenny McCormack)
View all headers
I have an Expect program that takes a single command line parameter, which
is a filename (which must exist).  The program starts with:

    #!/usr/bin/expect --
    if {$argc != 1 || ![file exists $argv]} { puts "Error";exit 1 }

This works fine as long as the filename is "normal" - i.e., doesn't contain
any spaces (and/or perhaps other weird characters).  However, if it has a
space, then the "file exists" check fails, because the actual value of
$argv is something like:

    {/path/to/file name with spaces}

The curly braces foo up the "file exists" check.  I am able to workaround
this by adding the following line before the above "if" statement:

    set argv [join $argv]

And this seems to be the fix.  As far as I can tell, the above line doesn't
break anything.  In fact, I've used this kludge/hack in the past, so I
didn't have to invent it anew today.  But why is it necessary?  Isn't it
weird that it is necessary?
1
--
In the corner of the room on the ceiling is a large vampire bat who
is obviously deranged and holding his nose.


Subject: Re: Why do I need to "join" it?
From: saitolo...@gmail.com
Newsgroups: comp.lang.tcl
Organization: Aioe.org NNTP Server
Date: Sat, 14 May 2022 18:52 UTC
References: 1
Path: i2pn2.org!i2pn.org!aioe.org!a5rWVvs5S5ZXUwkNcVnRMw.user.46.165.242.91.POSTED!not-for-mail
From: saitolo...@gmail.com
Newsgroups: comp.lang.tcl
Subject: Re: Why do I need to "join" it?
Date: Sat, 14 May 2022 14:52:20 -0400
Organization: Aioe.org NNTP Server
Message-ID: <t5otpa$s5p$1@gioia.aioe.org>
References: <t5o3mr$71or$1@news.xmission.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Info: gioia.aioe.org; logging-data="28857"; posting-host="a5rWVvs5S5ZXUwkNcVnRMw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.1
Content-Language: en-US
X-Notice: Filtered by postfilter v. 0.9.2
View all headers
On 5/14/22 7:27 AM, Kenny McCormack wrote:
I have an Expect program that takes a single command line parameter, which
is a filename (which must exist).  The program starts with:

     #!/usr/bin/expect --
     if {$argc != 1 || ![file exists $argv]} { puts "Error";exit 1 }

....

     {/path/to/file name with spaces}

The curly braces foo up the "file exists" check.  I am able to workaround
this by adding the following line before the above "if" statement:

     set argv [join $argv]

And this seems to be the fix.  As far as I can tell, the above line doesn't
break anything.  In fact, I've used this kludge/hack in the past, so I
didn't have to invent it anew today.  But why is it necessary?  Isn't it
weird that it is necessary?


Hello,

It is not weird, it is documented and is pretty common in some other languages too.  While you may have gotten away with it in the past, it is purely due to the number and nature of the arguments you have worked with.  The code is buggy. Another latent error in your code which you haven't seen yet is that you should use lindex with argv.


"argv" is handled as a list.  I don't have it handy at the moment but the proc man page should have a nice description on it: any and all remaining (unnamed) arguments from the command line are collected, put into a list, and provided to the proc as a list named "argv".  If you have spaces within an individual argument's data, you would need to escape that somehow in the command line.  There may be no way to properly reconstruct the original argument data in the proc otherwise (think of multiple file names with spaces in them).






Subject: Re: Why do I need to "join" it?
From: Kenny McCormack
Newsgroups: comp.lang.tcl
Organization: The official candy of the new Millennium
Date: Sat, 14 May 2022 20:05 UTC
References: 1 2
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!xmission!nnrp.xmission!.POSTED.shell.xmission.com!not-for-mail
From: gaze...@shell.xmission.com (Kenny McCormack)
Newsgroups: comp.lang.tcl
Subject: Re: Why do I need to "join" it?
Date: Sat, 14 May 2022 20:05:20 -0000 (UTC)
Organization: The official candy of the new Millennium
Message-ID: <t5p220$7gib$1@news.xmission.com>
References: <t5o3mr$71or$1@news.xmission.com> <t5otpa$s5p$1@gioia.aioe.org>
Injection-Date: Sat, 14 May 2022 20:05:20 -0000 (UTC)
Injection-Info: news.xmission.com; posting-host="shell.xmission.com:166.70.8.4";
logging-data="246347"; mail-complaints-to="abuse@xmission.com"
X-Newsreader: trn 4.0-test77 (Sep 1, 2010)
Originator: gazelle@shell.xmission.com (Kenny McCormack)
View all headers
In article <t5otpa$s5p$1@gioia.aioe.org>,  <saitology9@gmail.com> wrote:
....
Hello,

Thank you for your response.

However, it does not tell me anything I didn't already know.

But thank you anyway.

P.S.  Yes, it is weird.  Why is join needed?  I.e., am I correct in
assuming that it only puts the {} in, when there is a space (or some other
"weird" character) in the filename?


--

    "This ain't my first time at the rodeo"

is a line from the movie, Mommie Dearest, said by Joan Crawford at a board meeting.


Subject: Re: Why do I need to "join" it?
From: mango
Newsgroups: comp.lang.tcl
Date: Sat, 14 May 2022 20:46 UTC
References: 1
X-Received: by 2002:a37:bc8:0:b0:69f:a898:cefb with SMTP id 191-20020a370bc8000000b0069fa898cefbmr7538830qkl.525.1652561183088;
Sat, 14 May 2022 13:46:23 -0700 (PDT)
X-Received: by 2002:a05:6808:1587:b0:326:cc22:9984 with SMTP id
t7-20020a056808158700b00326cc229984mr5082892oiw.3.1652561182745; Sat, 14 May
2022 13:46:22 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!feed1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.tcl
Date: Sat, 14 May 2022 13:46:22 -0700 (PDT)
In-Reply-To: <t5o3mr$71or$1@news.xmission.com>
Injection-Info: google-groups.googlegroups.com; posting-host=24.176.163.173; posting-account=ZFot6woAAABKx26r18WnGS2aDcK8wnRB
NNTP-Posting-Host: 24.176.163.173
References: <t5o3mr$71or$1@news.xmission.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <4fcfafc6-bf0e-42c7-9558-565efd03489fn@googlegroups.com>
Subject: Re: Why do I need to "join" it?
From: amango...@modelrealization.com (mango)
Injection-Date: Sat, 14 May 2022 20:46:23 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 1490
View all headers
On Saturday, May 14, 2022 at 4:27:28 AM UTC-7, Kenny McCormack wrote:
I have an Expect program that takes a single command line parameter, which
is a filename (which must exist). The program starts with:

#!/usr/bin/expect --
if {$argc != 1 || ![file exists $argv]} { puts "Error";exit 1 }

[snip]

Since argv is a list, the proper way to obtain the first element is, [lindex $argv 0].


Subject: Re: Why do I need to "join" it?
From: briang
Newsgroups: comp.lang.tcl
Date: Sat, 14 May 2022 21:24 UTC
References: 1 2 3
X-Received: by 2002:a05:622a:44b:b0:2f3:f495:386b with SMTP id o11-20020a05622a044b00b002f3f495386bmr10003027qtx.349.1652563440688;
Sat, 14 May 2022 14:24:00 -0700 (PDT)
X-Received: by 2002:a05:6870:424b:b0:ed:97b3:7240 with SMTP id
v11-20020a056870424b00b000ed97b37240mr12002455oac.238.1652563440407; Sat, 14
May 2022 14:24:00 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!feed1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.tcl
Date: Sat, 14 May 2022 14:24:00 -0700 (PDT)
In-Reply-To: <t5p220$7gib$1@news.xmission.com>
Injection-Info: google-groups.googlegroups.com; posting-host=50.53.75.154; posting-account=f4QznQoAAAAjupLEpV87s_G-96g1Io1w
NNTP-Posting-Host: 50.53.75.154
References: <t5o3mr$71or$1@news.xmission.com> <t5otpa$s5p$1@gioia.aioe.org> <t5p220$7gib$1@news.xmission.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <62ddc814-113d-40fd-aedf-7e21b25f16a3n@googlegroups.com>
Subject: Re: Why do I need to "join" it?
From: bgriffin...@gmail.com (briang)
Injection-Date: Sat, 14 May 2022 21:24:00 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 3125
View all headers
On Saturday, May 14, 2022 at 1:05:25 PM UTC-7, Kenny McCormack wrote:
In article <t5otpa$s5p$1...@gioia.aioe.org>, <saito...@gmail.com> wrote:
...
Hello,

Thank you for your response.

However, it does not tell me anything I didn't already know.

But thank you anyway.

P.S. Yes, it is weird. Why is join needed? I.e., am I correct in
assuming that it only puts the {} in, when there is a space (or some other
"weird" character) in the filename?

It is not weird!  It is as designed.
As has been repeated here already, argv is a list.  It is NOT a scalar value.  Your code already asserts that argc == 1.  This value should always equal the list length of argv:  [llength $argv] == $argc
If you put 2 arguments on the command line, argc will be 2, and your test will error as it should.  The llength of $argv will also be 2.

Since argv is always a list, the code must index elements from the list, even if there is only one element.  The weird part, if any, is that your code just happens to work for the subset of filenames without spaces.  It happens to work because the script has a bug, i.e., not using [lindex].

Lastly, it is faulty to assume that the kind of a variable can be determined by looking at the value.  This is false.  The kind of a variable (i.e. list, scalar, dict, etc.) is determined by how it is used in the script.  The argv variable is created by tclsh as a list, therefore, any subsequent operations on it must be list operations.

I've written this response in a somewhat hash tone, sorry.  I do this because unless this fact about list values vs scalar values is deeply understood, programs written in Tcl will continue to be buggy. Code written to respect the "kind" of data will always be correct, at least with respect to manipulation of the datum.

-Brian



Subject: Re: Why do I need to "join" it?
From: saitolo...@gmail.com
Newsgroups: comp.lang.tcl
Organization: Aioe.org NNTP Server
Date: Sat, 14 May 2022 21:35 UTC
References: 1 2 3
Path: i2pn2.org!i2pn.org!aioe.org!a5rWVvs5S5ZXUwkNcVnRMw.user.46.165.242.91.POSTED!not-for-mail
From: saitolo...@gmail.com
Newsgroups: comp.lang.tcl
Subject: Re: Why do I need to "join" it?
Date: Sat, 14 May 2022 17:35:19 -0400
Organization: Aioe.org NNTP Server
Message-ID: <t5p7as$1405$1@gioia.aioe.org>
References: <t5o3mr$71or$1@news.xmission.com> <t5otpa$s5p$1@gioia.aioe.org>
<t5p220$7gib$1@news.xmission.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Info: gioia.aioe.org; logging-data="36869"; posting-host="a5rWVvs5S5ZXUwkNcVnRMw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.1
Content-Language: en-US
X-Notice: Filtered by postfilter v. 0.9.2
View all headers
On 5/14/22 4:05 PM, Kenny McCormack wrote:
In article <t5otpa$s5p$1@gioia.aioe.org>,  <saitology9@gmail.com> wrote:
...
Hello,

Thank you for your response.

However, it does not tell me anything I didn't already know.


Hello,

I re-read what I wrote and I believe there is a lot of relevant info there on argv, how it is constructed, and what the ramifications are for passing data to proc's as unnamed arguments via argv.  You may or may not know this but the code you gave shows a lack of it in practice.

"argv" is a list and it is made up of whatever is found on the command line after the named arguments of the target procedure.  Therefore, you need to expect a list in it and use list commands to process it.

if {$argc != 1 || ![file exists $argv]} { puts "Error";exit 1 }

You can't use argv as the name of the file.



But thank you anyway.

P.S.  Yes, it is weird.  Why is join needed?  I.e., am I correct in
assuming that it only puts the {} in, when there is a space (or some other
"weird" character) in the filename?



Join is needed to convert a list of items into a single string which you later use as  file name.  You can't use a list as a literal value (nowwithstanding Tcl's lax treatment of single atomic element lists).

Please look up argv in the manuals.  Also try to extend your proc above to accept two file names (which may contain spaces) using the argv convention.  This may be more beneficial.



Subject: Re: Why do I need to "join" it?
From: Ralf Fassel
Newsgroups: comp.lang.tcl
Date: Mon, 16 May 2022 08:29 UTC
References: 1
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail
From: ralf...@gmx.de (Ralf Fassel)
Newsgroups: comp.lang.tcl
Subject: Re: Why do I need to "join" it?
Date: Mon, 16 May 2022 10:29:52 +0200
Lines: 52
Message-ID: <ygaee0tyj5r.fsf@akutech.de>
References: <t5o3mr$71or$1@news.xmission.com>
Mime-Version: 1.0
Content-Type: text/plain
X-Trace: individual.net y2XGa+5YUCakMJbuXmQN3Q8Ub6iDcJrZoWISTljvlL2ro+8ug=
Cancel-Lock: sha1:lIeV6AJU8BI80fy77LxCL7NlKdk= sha1:vSEf33ug5OrOGtXK1Z1zbcqaVU4=
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.3 (gnu/linux)
View all headers
* gazelle@shell.xmission.com (Kenny McCormack)
| I have an Expect program that takes a single command line parameter,
| which is a filename (which must exist).  The program starts with:

|     #!/usr/bin/expect --
|     if {$argc != 1 || ![file exists $argv]} { puts "Error";exit 1 }

| This works fine as long as the filename is "normal" - i.e., doesn't contain
| any spaces (and/or perhaps other weird characters).  However, if it has a
| space, then the "file exists" check fails, because the actual value of
| $argv is something like:

|     {/path/to/file name with spaces}

| The curly braces foo up the "file exists" check.  I am able to workaround
| this by adding the following line before the above "if" statement:

|     set argv [join $argv]

| And this seems to be the fix.

Wrong fix.  As you know, argv is a list.  If you use $argv in a string
context (as in 'file exists', which expects a single argument filename),
the string representation of that list is substituted.  And if the list
contains spaces, TCL needs to quote these spaces in case you want to
re-use the string representation as a list again - this is why the "{}"
creep in.

To access the individual elements of a list, you need to use lindex:

  set filename [lindex $argv 0]
  set second_arg [lindex $argv 1]
  set third_arg [lindex $argv 2]
 
  # or alternatively all in one go:
  lassign $argv filename second_arg third_arg

  if {![file exists $filename]} ...


Using 'join' on a list just joins the individual parts of the list with
spaces, which sometimes works for filenames.  But as you have noted, in
other cases (double space in filename) it fails, so this is not a
solution.

Also, just printing 'Error' in case of failure is not very helpful to
the end-user (which might be you in three months, wondering what 'Error'
might mean).  Just add "input file '$filename' does not exist" to the
error message.

HTH
R'


1

rocksolid light 0.8.3
clearneti2ptor