On Sat, Apr 22, 2006 at 05:52:31PM +0800, Audrey Tang wrote: : During my S03 cleanup today, I noticed that because *$fh and **$fh : interpolates into the current argument list, it's always the same as : =$fh under list context. So I wrote this paragraph: : : [Conjectural: File handles interpolates its lines into positional : arguments (e.g. to C<statement_control:<for>>), so we can make C<=$fh> : always return the next item, regardless of the context: : : for *$fh -> $line { ... }; # read one line at a time : for **$fh -> $line { ... }; # read up all lines first : say(=$fh, =$fh, =$fh); # print three lines : ] : : However, this will mark a departure from the context-sensitive use of =$fh: : : say =$fh; # prints everything : =$fh ~~ /.../; # reads just the first line : : So, I wonder if the "=" operator can always just mean "return the next : thing", and leave the Perl5-esque context-sensitiveness to the : readline() function. I've written (scalar <FH>) many times in Perl 5 : code, and I wonder if a reliably-scalar-context iterator can be a win : here... Thoughts?
Hmm, I almost never write "scalar <FH>" because I very rarely want to input a single line in list context. But leaving that aside... There is some merit to the proposal, but lots of ramifications as well. First, it loses some of the original motivation for using prefix:<=> in the first place, which was intended to be remind one of the lines (plural) in the file. By rights, the operator should be renamed to prefix:<-> if it's just one line. (Which could actually be made to work, since math is not required skill of iterators.) Or if we escape ASCII, there's always the prefix:<δΈ€> operator, which does an even better job of suggesting "oneness", at least in some cultures. :) On the other hand, -<> makes a pretty pathetic fish operator. So for the sake of argument, let's keep it =<> for the moment. But ignoring the tail leads us to the head end of the fish. What do we do about $ARGS? We could say this: =$fh : *$fh :: =<> : *<> Now if you analyze *<> as a unary * plus a null list, it's obviously stupid to be interpolating 0 arguments at this point, so pragmatically speaking something else is meant by this utterance, and we could make it mean "read all the lines of $ARGV" easily enough. On the other hand, we've just clarified the distinction between @x and @@x, so one could assert that @$fh not only is more meaningful to the casual observer, but automatically gives us a multidimensional view via @@$fh if $fh can supply a multidimensional view. Which it can, if $fh represents multiple files. Which means @@$ARGS represents the lines from each of the $ARGS files, with each file as an independent *lazy* slice. There's potentially some power in that. But if we do that, then the obvious shortcut is @<> and @@<> if we want to keep our various little fishies and our mama fishie too. Unfortunately, @<> is currently defined to mean $/{''}[] or some such. We could just swipe it, since almost nobody's going to be doing a null key capture. Or we could just say you have to write @($ARGS) and @@($ARGS) for that. Or maybe @(<>) and @@(<>) for short. (Presumably the @ forms would be for rvalue use only--at least till MJD gets ahold of them--but I don't think that's terribly important one way or the other in a huffman fight.) Another option is to just give up on the <> meme. We just invented the Whatever token *, so maybe in an iterator context Whatever means $ARGS. Then we get =* as reading a line from $ARGS, and @* perhaps as reading all the lines, or @(*) if you're worried about the twigilhood of *. Unfortunately ** wouldn't work in that case to mean *(*), but would be taken as a WhateverEagerly token maybe. One thing we talked about on #perl6 is the possibility of just making Whatever in list context iterate $ARGS: for * {...} but that seems perhaps overhuffmanized, and insufficiently contextual. (Though if we did do that, presumably for ** {...} would be the eager version...) Anyway, that's probably not going to fly. There's also the line of thought that says if *$fh is a splatty filehandle reading 0 or more lines, then +$fh should read one or more lines, and then obviously ?$fh should read 0 or 1 lines. And what would a filehandle mean in boolean context except "Can I read more?" Of course, this does violence to the current meanings of prefix:<+> and prefix:<?>, insofar as the first always returns a number and the second always returns a boolean. So that doesn't fly either. For that matter, that's also the problem with using - to indicate one line. If we do say that $fh.as(Array) pulls all the lines from the iterator destructively (though lazily), then it logically follows that $fh.as(Scalar) pulls one line. Which means instead of say(=$fh, =$fh, =$fh); # print three lines you'd just say say($$fh, $$fh, $$fh); # print three lines and then maybe we retire = entirely from the iterator business, especially considering the ugliness of it's #1 use: my $nextline = =$fh; I think my $nextline = $$fh; is a bit prettier. But if $ indicates the forced scalar version, than symmetry says that @ is the forced list version. And where does that leave *$fh? Perhaps as the linguistically lazy one, it's the logical choice to do one iteration in scalar context and all iterations in list context, but only after it knows the context upon binding. And then if you really want to interpolate all the iterator values as arguments you'd have to say [EMAIL PROTECTED] or some such. But you could also intepolate only the first argument as *$$fh. No decisions yet, but you only asked for Thoughts. :-) Larry