On 2009-Aug-15, at 9:22 am, Jon Lang wrote:
IOW, your "outside the file" stuff is whatever can be done without
having to open the file, and your "inside the file" is whatever only
makes sense once the file has been opened.  Correct?  If so, could you
give some examples of how such a distinction could be beneficial, or
of how the lack of such a distinction is problematic?

Well, I definitely think there needs to be a class that combines the inside and the outside, or the data and the metadata. Certainly the separate parts will exist separately for purposes of implementation, but there needs to be a user-friendlier view wrapped around that. Or maybe there are (sort of) three levels, low, medium, and high; that is, the basic implementation level (=P6 direct access to OS- and FS- system calls); the combined level, where an IO or "File" object encompasses IO::FSnode and IO::FSdata, etc.; and a gloss-over-the- details level with lots of sugar on top (at the expense of losing control over some details).

In fact, having q, Q, or qq involved at all strikes me as wrong,
since those three are specifically for generating strings.

Pathnames still are strings, so that's fine. In fact, there are different things going on here; one is to have a way of conveniently quoting strings that contain a lot of backslashes. Just as Perl lets you pick different quotation marks, to make it easier to quote strings that have a lot of " or ' characters, so it should have a way to make it easy to quote strings with a lot of backslashes. (The most obvious example being Windows paths; but there are other possibilities, such as needing to eval some code that already has a lot of backslashes in it.)

Now, you can already turn backwhacking on or off via Q's :backslash adverb; Q:qq includes :b (and Q:q recognises a few limited escape sequences like \\). So you could say Q[C:\some\path], and you could add scalar interpolation to say Q:s[C:\some\path\$filename]. But there's no way to have all of: literal backslashes + interpolation + escaped sigils.

Perhaps instead of a simple :b toggle, we could have an :escape<Str> adverb that defaults to :escape<\>? Then you could have Q:scalar:escape("^")[C:\path\with\literal^$\$filename].

The ultimate in "path literals" would be to establish a similar
"default delimiter".  [...]
  `path`.size # how big is the file?  Returns number.

There's something that slightly jars me here... I don't like the quotation returning an IO object. (I like the conciseness, but there's something a bit off conceptually.) Let's see, `exec command` bugs me too -- it's quoting something and then doing something with the quoted string. (It's not entirely unreasonable as a cryptic shorthand in the shell, but I think P6 should have an actual command for that (e.g. the proposed run-gather()).) Similarly, in this example, we're quoting a pathname, and then creating an IO object from it.

So I don't like the quoting-and-then-using, when done by the quotation marks, although having a function (really, macro) that does its own quoting seems fine: "io /some/autoquoted/filename". And /regex/ doesn't bother me either. Hm. Ah, but an instant regex isn't doing anything besides creating an object -- it is comparable to q[foo] creating a Str. So `exec me!` bothers me because it isn't just returning some kind of "System::Command" object, it's more like creating the object and then calling the .run() method on it too. / pattern/ doesn't *do* anything with the regex.

Now, isn't Q:path[/some/file] just creating an IO object? Unlike / foo/, where "foo" just IS the pattern, "/some/file" is *not* an IO object, it's just a filename. So if the special path-quoting returned an IO::File::Name object, I would be perfectly happy. But you can't have $filename.size -- a fileNAME doesn't have a size, the file itself does. To get from the filename to the file, you need another step, and it's that extra step I don't like being hidden inside quotation marks, just as in the `exec` case.

Anyway, that's a subtle but important point, I think. Fortunately, in the end it doesn't have to work out much differently: instead a "path" quoter that does IO-stuff, have a "path" function (macro, whatever) that does quoting stuff.

    $file = new IO::File(FSNode => "/path/to/file");
    $file = path "/path/to/file";
    $file = io /path/to/file;
    $file = file://localhost/path/to/file;

Incidentally, I do think it's worth having an actual File::Name type, even though names are really just strings. For example, not all strings are valid filenames if the FS doesn't handle Unicode. However, Strings should get transparently cast to IO::Names wherever possible, so the typical user would never have to notice the difference.

IO::Name objects also provide a way to concatenate items correctly, as per Hinrik's original post regarding a better way to do File::Spec::catdir. I completely agree that we should encourage use of the official way to join paths, and using catdir() everywhere is too verbose, and simply leads to people doing "$dir/$file" anyway. But I'm not keen on using a variation on qw// that splits on whitespace; spaces aren't that uncommon in filenames, and look unnatural to me as a path-separator. However, an infix:</> operator on IO::Names would allow nice, simple, and familiar expressions like $path/$file.

The objects would have to be IO::Names, not Strings, though it should work with IO::FSNodes or whatever (delegating to their .names), and infix:</>(IO::Name, Str) should probably also work. That means at least the first operand has to be an IO object, which can easily be done even if you have only strings to work with by:

my $output = io $dir/"output.txt"; # where $dir is a Str; io $dir generates the object my $output = path $dir/"output.txt"; # or this, if we have path() rather than io(), etc.

On the other hand, Str "/" may be officially OK as a path separator, so that {join "/", $dirstring, $filestring} will work, assuming that we can require IO objects always to parse a literal string the right way. (I.e. "/" is made to represent the official cross-platform path separator. Unless you parse some literal text with Q:ntfs, which parses a literal "\" as "/"?? Or say "use path-separator '\';" or something!)

In fact, path literals may be more pattern-like than string-like, when
and if you start taking wildcard characters into account:

 if $file ~~ path[./*.txt] {
     say "$file is a text file in the current working directory."

Is that just a regex, in fact? Or to allow for special quoting, Q:special-path-adverbs:regex? In other words, certain IO functions would be able to take a regex instead of a string for the Pathname arg, and return an array of however many items matched.

Though, to speak of file-types, this particular example would I think better be handled by:

    if $file.type ~~ MIME("text/plain") {...}

or just:
    if $file.type ~~ "text/plain" {...}

since .type() presumably returns a Data::Type::MIME object to begin with. (Or even better, a Data::Type::UTI object, since UTIs are a more useful superset of MIME. Is there any system that would be even better than UTIs?)

<http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/understand_utis_conc/understand_utis_conc.html >


Reply via email to