I can only argue that since the function's name 'dir' reminds a shell level command, and 'ls a' and 'dir a' work in a certain way, I was expecting that the function 'dir' worked in the same way, following the Principle of Least Surprise :-)
On Tue, Nov 27, 2018 at 1:37 AM Trey Harris <t...@lopsa.org> wrote: > > On Mon, Nov 26, 2018 at 19:26 Trey Harris <t...@lopsa.org> wrote: > >> >> >> 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")) >> > > Oops, ignore the changing variable names here; I was copying lines from a > REPL session where I'd used `$f`, and then I changed `$f` to match `$i` in > the text before it and didn't fully complete the renaming. It's just a > single variable. > > >> 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.) >> > -- Fernando Santagata