Nathan Wiger writes:
: You know, I was just thinking about this, and I agree with Dan. Actually,
: there's some big problems in trying to get rid of <> and make Perl do the
: "right thing" in boolean context (like the while loop example). Consider:
: 
:    $FH = open "</etc/motd";
:    die "No good" unless ($FH);    # ???

You're right, that's a severe problem.

: What does that do? Per the proposal, $FH in a boolean context is supposed to
: call its next() method to get the next line. So, does that fail because the
: handle wasn't opened (and hence $FH was never defined) or because /etc/motd
: is zero-length?
: 
: And having to write "$line = next $FH" is already getting cumbersome, to be
: honest.

True 'nuff.

: I say we should combine the two concepts. Why not make <> a shortcut to the
: proposed new general-purpose-iterator concept? So:
: 
:    $line = $FOO.next;        # yuck, I agree with Dan
:    $line = next $FOO;        # better...
:    $line = <$FOO>;           # aaah :-)
: 
:    print while ($FOO);       # infinite, assuming $FOO defined
:    print while ($FOO.next);  # while reading the file
:    print while (<$FOO>);     # still my favorite
: 
: Otherwise, it seems like there's a lot of Black Magic with calling next()
: automatically, and for something as fundamental as I/O that makes me really
: nervous.

I expect the real choice is between <$FOO and <$FOO>.  I can convince
myself pretty easily that a unary < is just another name for "next", or
"more", or something.  On the other hand <$FOO> has history.  And if
one special-cases <$...>, we could also have <foo bar baz> as a qw()
replacement.  All we'd be doing is taking that syntax away from
globbing, and giving it to qw, more or less.  (Less, because I'd like
<foo bar baz($xyz)> to mean {foo => 1, bar => 1, baz => $xyz} or some
such, where the 1's are negotiable.)

But maybe I should hold out for «» meaning qw() eventually.  If we
continue to require quotes on the string of <<"END", we could even use
<< foo bar baz($xyz) >> as an ASCII workaround, I suppose.  That's not
much more readable than qw(), I admit.

That leaves < free to be either a prefix or circumfix operator of
arbitrary complexity.

If < is a unary operator, then one could have an arbitrary expression
returning an iterator:

    $line = <somefunc();

For a circumfix, you could just treat <> as funny parens:
 
    $line = <somefunc()>;

On the other hand, I wouldn't want to go so far as to require

    <1..10>

merely to make the iterator iterate.  Saying

    @foo[1..10]

ought to be enough clue.  But does that mean that

    %foo{$STDIN}

should read one value or all of them?  Or some number depending on the number
of values expected in the context?  And now we're back to the question
of slice context, really.  Obviously, given a list flattener *, we'd
expect

    %foo{*$STDIN}

to return all the values.  Maybe then

    %foo{<$STDIN}

returns exactly one value, and

    %foo{$STDIN}

guesses.

Looking at it from the iterator object end, there might really be three
methods:

    $STDIN.next         # Return one element regardless of context.
    $STDIN.more         # Return number of element wanted by context.
    $STDIN.all          # Return all element regardless of context.

Or maybe there's only a "more" method, and you simply have to force the
context if you don't want it to guess.  We don't actually have a good
notation for forcing a scalar context yet, let alone a scalar context
wanting a certain number of arguments.  Doing violence to our current
notions of what various prefix operators currently mean, we might want:

    $$STDIN             # Return one element regardless of context.
    @$STDIN             # Return number of element wanted by context.
    *$STDIN             # Return all element regardless of context.

or

     $STDIN             # Return one element regardless of context.
    =$STDIN             # Return number of element wanted by context.
    *$STDIN             # Return all element regardless of context.

or

    $-STDIN             # Return one element regardless of context.
    $=STDIN             # Return number of element wanted by context.
    $*STDIN             # Return all element regardless of context.

or

    $:$STDIN            # Return one element regardless of context.
    @:$STDIN            # Return number of element wanted by context.
    *:$STDIN            # Return all element regardless of context.
or

    $($STDIN)           # Return one element regardless of context.
    @($STDIN)           # Return number of element wanted by context.
    *($STDIN)           # Return all element regardless of context.

or

    $:$STDIN            # Return one element regardless of context.
      $STDIN            # Return number of element wanted by context.
    @:$STDIN            # Return all element regardless of context.

or

    $<$STDIN            # Return one element regardless of context.
     <$STDIN            # Return number of element wanted by context.
    @<$STDIN            # Return all element regardless of context.

or some other casting mechanism yet to be devised.

The basic underlying question is, what is the context that should fire
off an iterator?  Everyone thinks @foo[1..10] should just do the right
thing, whatever that is.  Assuming the following makes an iterator,
and doesn't set $iter to 1 the first time through:

    $iter = 1..10;

How many of these work?

    while ($x = @foo[$iter]) { ... }
    while ($x = <$iter>) { ... }
    while ($x = $iter) { ... }
    for ($iter) { ... }

I think that iterators must be dereferenced by something explicit, and
we will have to be very clear as to what is explicit enough.  Subscripts
may be explicit enough:

    @foo[$iter]         # okay?
    @foo[<$iter>]       # kludgey

Obviously, $iter.method doesn't want to iterate:

    $iter.more          # can't iterate, or you call $iter.more.more.more...
    <$iter>.more        # okay, iterates over some iterators.

Well, that's enough brainwracking for the moment.  Gloria is making me
go eat something...

Larry

Reply via email to