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