Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

=$fh vs *$fh

0 views
Skip to first unread message

Audrey Tang

unread,
Apr 22, 2006, 5:52:31 AM4/22/06
to Perl 6 Language
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?

Thanks,
Audrey

signature.asc

Larry Wall

unread,
Apr 22, 2006, 10:40:45 PM4/22/06
to Perl 6 Language
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

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 *@$fh or some such. But you could also
intepolate only the first argument as *$$fh.

No decisions yet, but you only asked for Thoughts. :-)

Larry

Audrey Tang

unread,
Apr 23, 2006, 9:39:10 AM4/23/06
to Perl 6 Language
Larry Wall wrote:
> 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, maybe * plus a null list, namely *(), has a higher
purpose, where it can mean *$/, which is very very very useful. To wit:

grammar Java;
rule statement {
| <block>
{ Block.new(*()) } # Java::Block.new(block => $<block>)

| if \( $<cond> := <expr> \) <statement>
[ else $<else_statement> := <statement> ]?
{ If.new(*()) }

| for \(
<init> ;
$<cont> := <expr>? ;
$<next> := <expr>
\)
<statement>
{ For.new(*()) }

| ...
}

I think *() above is more visually distinct than *$/.

> (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.)

Lvalue @$fh can be fun too indeed, but I guess it depends on how the $fh
is constructed. :-)

> 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 *.

I think I like this alternative best. The <> meme never really felt
comfortable to me, as the empty string-list "magic" may be too much magic.

> 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

One problem is that while repeated @$fh conceptually returns the same
thing, $$fh here would iterate instead of merely dereference, which
makes it carry its own state. If "=" means something like "each(%kv)"
in Perl 5, and we get =@array as well for iterating over elements, then
it makes more sense for that purpose for =$fh as well.

Thanks,
Audrey

signature.asc

Juerd

unread,
Apr 23, 2006, 12:08:27 PM4/23/06
to perl6-l...@perl.org
Larry Wall skribis 2006-04-22 19:40 (-0700):

> Hmm, I almost never write "scalar <FH>" because I very rarely want to
> input a single line in list context. But leaving that aside...

I've used it a lot.

I do tend to use it less often as I move away from line based text
documents for storage.

> [101 lines]

I wish I had time to read it all.


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

0 new messages