On Mon, Nov 26, 2018 at 04:56 Fernando Santagata <nando.santag...@gmail.com>
wrote:

> On Sun, Nov 25, 2018 at 5:34 PM Brad Gilbert <b2gi...@gmail.com> wrote:
>
>> The reason `dir('a', test => { .IO.d })` doesn't work like you expect
>> is that it is passed strings.
>>
>
> Thank you!
> I could have inferred that from the declaration of the 'test' argument
> here https://docs.perl6.org/routine/dir where the test is being done
> against '.' and '..', two strings:
>
> sub    dir(Cool $path = '.', Mu :$test = none('.', '..'))
>> method dir(IO::Path:D: Mu :$test = none('.', '..'))
>>
>
> but I guess it's a long stretch.
> Maybe a note in the docs would be useful to others.
>
>
>> I would argue that inside of the `test` that `$*CWD` should be set to
>> `a`, and/or the values should be IO objects.
>> (They are going to become IO objects eventually anyway.)
>>
>
> Indeed I think that even tough one can do any kind of test on the
> directory's content, the most usual ones are those using the file test
> operators, so defaulting to IO is probably more useful than defaulting to
> Str.
>

I'm not sure that's true. I think it's a question of following the
Principle of Least Surprise.

The only substantive difference between `my $i = "foobar".IO` and `my $s =
"foobar"` besides needing to stick the `.IO` in when you want to do IO-y
things with `$s` is that `$i` retains the knowledge of $*CWD at the time of
instantiation. But `dir` always returns paths that stringify _relative to
`$*CWD` at the time of the `dir` call._ Notice the difference between
`$i.gist` (which, if evaluated, will not consistently re-create the
original object) and `$i.perl` (which will):

    > $f.gist
    "foobar".IO
    > $i.perl
    IO::Path.new("foobar", :SPEC(IO::Spec::Unix),
:CWD("/home/trey/perl6/rakudo-star"))
    > chdir "/tmp"
    "/tmp".IO
    > $f.gist
    "foobar".IO
    > $i.perl
    IO::Path.new("foobar", :SPEC(IO::Spec::Unix),
:CWD("/home/trey/perl6/rakudo-star"))

The string, OTOH, is also relative to the `$*CWD` at the time of the
`dir()` call, but if you call `.IO` on it after changing directories, the
path object is interpreted relative to the new directory. This is
unsurprising; what _would be_ surprising is if a string changed as a result
of external program state.

Large-scale file-munging operations have always been squarely in Perl's
wheelhouse, and doing fancy operations with complex subtrees (such as
syncing, normalizing, archiving, collating, etc.) are common.

The string doesn't offer as much in the way of features, but I think it
behaves much more predictably when doing these sorts of operations. If you
`chdir $dest` after the `dir` but before doing your munging, then you must
remember to prepend the old working directory if you need to access the
original file (i.e., `$src = $*CWD;  for @files -> $f { $src.add($f) ...
}`), while the new files would just be `$f`. If you don't change
directories, then you must say `$dest.add($f)` to refer to the new files,
while the old file is just `$f`. But in either case, it's unsurprising and
predictable.

If, OTOH, these were IO objects, if you changed directories, you'd think
from the gist that you'd do the same. And if you don't change directories,
you _could_ do the same (`$dest = "/destdir".IO; $dest.add($f)` works using
the gist). But if you do change directories, it's now the _old file_ that's
just `$f`; the new file becomes `$*CWD.add($f)`. This feels quite strange
and surprising to me.

The very slight keystroke-saving convenience of not requiring the outputs
of `dir` to be followed with `.IO` before doing IO operations on individual
IO objects in-place doesn't seem worth the strangeness of their behavior
when doing bulk operations on them from a distance.

(I was thinking through possible have-your-cake-and-eat-it-too solutions
like `.gist` and `.path` of IO objects created from strings changing their
string representation if and only if you changed working directories and
these all seem to just Waterbed Complexify the problem elsewhere. Perhaps
someone can come up with an everybody-wins solution—but except for moving
the filetest operations into `Cool` so they work like in Perl 5, a ship
that's already sailed, I can't think of one.)

Reply via email to