On 10/21/23 20:50, Ralph Mellor wrote:
Hi again. :)

Let me try again. I'll try cover things more clearly.

----

#1 There was/is a bug in your code, or at least code that you
say isn't working on your system. (It works on glot.io. See #3)

```
$WanIpFileName.IO.open(:w);
spurt "$WanIpFileName", "New File Opened";
```

These two lines clash badly. They are a bug waiting to
happen. The glot.io system resolves the clash in your
favor, so the clash isn't apparent. You are saying that
on your Windows system, the code fails.

The simplest thing to do is just fix the bug, rather than
worry about understanding it. The simplest way to fix
the bug is to simply drop the first line. It's redundant at
best, and causes the bug at worst, so just get rid of it.

If you don't want to understand the bug, but do want to
know about the other issues, skip ahead to #2 or #3.

----

In case you *do* want to understand the bug, let's
start with another way to fix the bug. You could write:
```
my $handle = $WanIpFileName.IO.open(:w);
$handle.spurt: "$WanIpFileName", "New File Opened";
```
That works, and should work on Windows.

This time the code *saves the file handle* corresponding
to the first line, and then uses that handle as the invocant
of a `.spurt` *method*, thus connecting the handle opened
in the first line to the `spurt` done in the second line.

Maybe *that* has explained all you need to know. If so,
feel free to skip ahead to #2 or #3.

Repeating the two lines that clashed:
```
$WanIpFileName.IO.open(:w);
spurt "$WanIpFileName", "New File Opened";
```

The first line opens the file in write mode -- and then
leaves it like that and throws away the file handle.

That's an issue. If you understand why it's an issue,
then great. If you don't, then that's OK too, and I'll
move on, because it isn't too important.

The second line has no idea the first line opened the
very same file it's just about to open, so it tries to open
it *again*, write to the file handle, and then close it.

Finally, at program exit, the file system tries to clean
up an exiting process, eg closing any file handles left
open and resolving clashes like your code generates.

On some systems the code will succeed. On your system
you say it doesn't. See #3 for demo and further discussion.

----

#2 There was/is a doc failure. I now see another one or two.

The doc failed to say that `spurt` opens the file. It should.

(Then you would presumably have understood you did not
need the `open` line.)

The doc failed to say `open` returns a file handle. It should.

(Then you would presumably have understood that if you
used an `open` line, you needed to keep the file handle
and use a `.spurt` *method* on that file handle.)

The example doc you looked at includes a line that does
the equivalent of `touch`. You thought you could use it
but chop off the `.close`.

(But you didn't realize you needed to keep the file handle,
as just explained.)

----

#3 There is a Windows difference. Your code runs fine on glot.io.

Please click this link, and then the Run button:

https://glot.io/snippets/gpv7tdaca0

That contains your code. And it's working. The difference is it's not Windows.

NB. Each time you click Run, glot.io automatically cleans the
file system. Every time. That's why it always says 'file does
not exist' at the start. Every time.

NB. I added the lines declaring the missing variable and sub,
and checking the file does not exist at the start, and some
commented out stuff and so on. Feel free to edit the code to
whatever you want if you want to. If you want to start over,
click refresh on your browser and click 'Reload'.

----
love, raiph



Hi Raiph,

Thank you for all the time you spent on this!  It
is extremely appreciated.



I wrote a little test code:

WinCreateFileTest.pl6
~~~~~~~~~~~~~~~
#!/usr/bin/env raku

sub DirectoryExists( Str $DirPath --> Bool ) { return "$DirPath".IO.d.Bool; } # $Full DirPath format is `H:\MyDocsBackup` sub DriveExists( Str $DriveLetter --> Bool ) { return "$DriveLetter".IO.e.Bool; } # $Drive Letter format is `A:\` sub Exists( Str $Path --> Bool ) { return "$Path".IO.e.Bool; } # file, dirctory, drive sub FileExists( Str $FilePath --> Bool ) { return "$FilePath".IO.f.Bool; } # $File Path format is `H:\IAmBackup`


my Str $TestFile = "WinEraseme.txt";

if FileExists( $TestFile )  {
   print "Previous $TestFile found.\n";
   spurt "$TestFile", "Old File Found\n";

} else {
   $TestFile.IO.open(:w).close;
   spurt "$TestFile", "New File Opened\n";
}

print Q[Now run `type ] ~ $TestFile ~ Q[`] ~ " to check your results\n"
~~~~~~~~~~~~~~~~~~


>del WinEraseme.txt

>raku WinCreateFileTest.pl6
Now run `type WinEraseme.txt` to check your results

>type WinEraseme.txt
New File Opened


>raku WinCreateFileTest.pl6
Previous WinEraseme.txt found.
Now run `type WinEraseme.txt` to check your results

>type WinEraseme.txt
Old File Found

~~~~~~~~~~~~~~~~~~~

So clearly, Windows Raku can not use spurt if a
previous file handle to the file is open/dangling.

~~~~~~~~~~~~~~~~~~~

So three things need to be fixed:

1)  I need to add `.close` to my code when all I want to
do is to create a file so that Raku (`spurt`, etc.) won't
get a dangling file handle.

2)  A discussion in the documentation need to be added
on how to create a file and how to handle dangling file
handles (add `.close`).

     $NewFileName.IO.open(:w).close;

3)  Raku needs to error out when a dangling file handle
causes the Windows file API to return an error

~~~~~~~~~~~~~~~~~~~~~~

My IO Keeper for create a file:


Create new file:
    Create a new file.  Note: overwrites an old file (not verified):
        "yourfilename".IO.open(:w).close

    Note: if you do not add the `.close` you will have a
          dangling file handle which will interfere with `spurt`.
          There are instances where you would want this handle though

~~~~~~~~~~~~~~~~~~~~~~

Love (maybe, perhaps, I ain't saying),
-T

Reply via email to