On Tue, Mar 15, 2005 at 12:21:19AM +0800, Autrijus Tang wrote:
: On Mon, Mar 14, 2005 at 08:06:08AM -0800, Larry Wall wrote:
: > On Mon, Mar 14, 2005 at 10:58:00PM +1100, Andrew Savige wrote:
: > : my $fh = open(@ARGS[0]);
: > : my @lines = =$fh;
: > : $fh.close();
: > : for @lines { print"$_" }
: > : 
: > 
: > Hmm.  It's probably a design bug.  I'm wondering if we have to specify
: > that ordinary assignment not only copies logically but, in fact, always
: > does ** flattening (immediate flattening) like Perl 5
: 
: Except ** does not flatten recursively, so:
: 
:     my $lines = [ =$fh ];
: 
: is still borked.
: 
: Do we want a *** "nuke everything flat" semantic device, if not the
: operator?  Or an eager context on the right hand side of "="?

I don't like ***.  As with :::: in rules, at some point you bail out
and go alphabetic.  So you might write that as

    my $lines = [ $fh.slurp ]

That doesn't work so well for

    my $lines = [ <>.slurp ]

though...

: On the other hand, we can alternatively specify that closing a
: file handle must force all thunks associated to it, i.e. in this
: case fill @lines with real data.  Pugs can do that just fine, but I
: have no idea how parrot is to achieve that...

I think we have to recognize that close() is a very non-FP-ish
operation.  It's essentially a kind of database commit, so that you
or someone else can reliable open the file and know what's going to
be there.  (We've essentally got the same problem writing lazy lists
to a file.)  So I guess the question is whether we can intuit the
intent of the programmer with the close.  There's the "I'm tired of
this filehande so close it logically but don't flush anything" vs the
"close this Right Now and flush everything Right Now and maybe even
fsync to disk to make jolly sure we're in a known state."

Since the earlier sentiment can be handled merely by letting the handle
go out of scope and get garbage collected someday, we probably have
to treat close as the more violent intention.  So if we can autoflush
output, we can also autofill input, but probably only for iterators
that were used in list context.  An iterator in scalar context expects
the close to truncate the rest of the input.  A Perl 5 programmer
expects that

    $foo = <$input>;

will stop working if you close $input, but will expect

    @foo = <$input>;

to produce all the values as if it had been eagerly flattened, because
that's what list context means in Perl 5.  In Perl 6, list context
merely means the promise of flattening, but in the case of

    $foo = [ =$fh ];

it means we have to fulfill the promise when $fh is closed.  It really is
a kind of COW situation, where close is construed as a write to the
effective length of the input.  The situation doesn't apply to

    $foo = [ 1... ];

because by default there's no handle to close on the infinite sequence.
Just as well, I suppose...

If we can capture the COW semantics, then we wouldn't necessarily have
to fix assignment, but it might be a good idea in any case to define

    @foo = (bar())

as

    @foo := [**bar()]

just to force programmers to make their eager/lazy intent clearer by
distinguishing = from :=.  Then the fact that = also does a top-level
copy just sort of naturally falls out.

Larry

Reply via email to