develooper Front page | perl.perl6.language | Postings from May 2001

Re: Apoc2 - <STDIN> concerns

Thread Previous | Thread Next
From:
Larry Wall
Date:
May 8, 2001 09:36
Subject:
Re: Apoc2 - <STDIN> concerns
Message ID:
200105081632.JAA13396@kiev.wall.org
Nathan Wiger writes:
: One thing I think we should avoid is as many "special cases" as possible.
: This is already why people hate <> currently - because it does both glob()
: and readline().
: 
: I would say that <> having history is actually a good thing. It's a
: foundation, really, since readline() is an iterator of sorts. All we'd be
: doing is generalizing the notion. Not only does it apply to files, but it's
: a shortcut to more() wherever you feel like using it.

Taking history into account is good, though I'd argue that now is the
proper time to change history, if we're going to change.  Perl would
never have been accepted in the first place had it been too different
from what came before, but now that Perl has its own momentum, we can
now look at how our own history gets in our way, and maybe do something
about it.

: As for <> as a qw() replacement, I think there are really two issues here.
: First, you're not really talking about a "replacement", since you're
: mentioning different semantics. So qw() will still be widely used. I suggest
: that we simply create another q-op to do the qw-ish things you're proposing.
: Perhaps qi() for "interpolate" or something else.

I think someone mentioned qh() for "hash".  That's a possibility, but I'd
still love to have enough brackets to give all of these standard shortcuts.

: Plus <> has the terrible
: problem that the POD C<> stuff does w/ embedded > chars. The really nice
: thing about the q's is you can choose any bracket you want. I think fleshing
: out this series of constructs makes the most sense.

No problem with that, though we probably need to reserve qA .. qZ for
the user.

: I'd so this differently, as hinted at above:
: 
:    %foo{<$STDIN>};    # return all values
:    %foo{<$STDIN);     # return one value
:    %foo{$STDIN};      # pass the $STDIN variable

Syntactically speaking it's too ambiguous to have both a unary < and a
bracketing <>.

: This is assuming that we want < to exist and have a different semantics. But
: I'm not sure that's a good idea. For one thing, you'd have to mention it
: several times if you want a couple values. I think there's got to be a
: better way to request the number of lines based on context.
: 
:    %foo{<$STDIN>};              # the whole thing
:    %foo{ (1..2) = <$STDIN> };   # anonymous list request?
:    %foo{ <$STDIN>[1..2] };      # or notate it as a list?
:    %foo{ ($STDIN.more)[1..2] }; # same thing
: 
: The last one seems to make sense (it's got those (localtime)[2,3] roots),
: with the third one as a shortcut.
: 
: > 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.
: 
: I think one method is the way to go. Let the subs and other contexts request
: the number of elements to get back using lazy evaluation:
: 
:    @foo[1..10] = <$STDIN>;     # get 10 iterations
:    $bar = <$STDIN>;            # next one
:    &lazy_sub(<$STDIN>);        # lazily
: 
: Assuming:
: 
:    sub lazy_sub ($a, $b, $c, $d) {   }
: 
: Then the last line above would lazily grab the next four lines.

I'd say that interpretation makes it a non-greedy equivalent to the
unary *, in that it defeats the prototype, er, signature.  That would
be an argument for unary <, I think.

: > 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.
: 
: Personally, I'd look at it differently. I don't think that getting a number
: of arguments out of a scalar context makes sense. Rather, I think you need
: to call a member function or do whatever to get a list, then lazily evaluate
: that.
: 
:    @a = $STDIN;    # @a gets a single element - $STDIN
:    @b = <$STDIN>;  # @b gets the entire contents of $STDIN
:                    # iterations via calls to more()

You don't actually get the entire contents of $STDIN.  You get a value
of $STDIN marked as a placeholder in the list assigned to @b, and that
placeholder says the RHS requested expansion of this in a manner
appropriate to the context supplied by the LHS.

Assuming Perl 5 semantics of = continue, a similar thing will happen
when you say:

    @a = @b;

or

    push(@c, @b);

Perl 6 might not put all the elements of @b on the stack as a temporary
list.  Rather, it might just put \@b marked as expandable.  (It might
also have to put some kind of copy-on-write lock on @b to keep it from
changing out from under, depending on how lazy the assignment (or
subroutine) actually gets about reading out the array.)

In this view, * and < could just be two different kinds of "expandable" flags.
But I'm uncomfortable with that, because I'd like to be able to say

    lazy_sub(<$STDIN, <$STDIN, <$STDIN, <$STDIN)

to feed four lines to lazy_sub without defeating the prototype, er,
signature checking.  Maybe you have to us *<$STDIN to do both.  But that
would probably say to slurp the whole rest of the file.

:    @c[0..3] = <$STDIN>;    # assuming we hadn't already emptied
:                            # it, this would lazily get 4 lines
:    @c[0..3] = more $STDIN; # same thing
: 
: > 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.
: 
: Again, I think this approach is barking up the wrong tree, respectfully. I
: don't think it makes sense. Which elements are you grabbing? The ones from
: more()? Why? Why would you automagically grab those instead of the ones from
:  bob() or jim()? Ok, we could define it that way, but I'd rather see:
: 
:    @a[0,1,2,3] = $jim.bob;
:    @b[4..5] = $foo.bar;
:    @c[9,10,11..13] = $jeff.more;    # just happens to have a <> shortcut

Yes, my basic feeling is that any variation in meaning of the iterator
should be driven by context, but how do we annotate that efficiently?

: Basically, <> is left as direct access to the iterator, but it's not
: magically called except where it clearly make sense (and I don't think
: normal variable manip like passing into subs and hashes should be in this
: category).
: 
: >     $<$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.
: 
: I'd do a variation on the above. Looking from a functional perspective:
: 
:      $STDIN.more          # context-dependent
:     ($STDIN.more)[0..3]   # just selected elements (lazily)
:     ($STDIN.more)[0..-1]  # forced all
: 
: Then we'd have the following shorcuts as a side-effect:
: 
:     <$STDIN>              # context-dependent
:    (<$STDIN>)[0..3]       # just selected elements (lazily)
:    (<$STDIN>)[0..-1]      # forced all
: 
: Seems to be easy and clean, without lots of new syntax.

I'd lose the parens, but yes, an official slice is one way to be explicit
about context.  But in a way that defers the problem to the slice notation.
What context would the following provide?

   <$STDIN>[somefunc()]

: >     for ($iter) { ... }
: 
: This is tricky. I see two ways. First, you could expand more()
: automatically, then go through its arguments. But I don't think that
: necessarily makes sense. Consider in Perl 5:
: 
:    $a = \@b;
:    for ($a) { ... }
: 
: This only gets one thing. And I know we're redoing semantics, but I think
: this is sensible. I don't want auto-element-grabbing-conversion. If I want
: to iterate, I think I want to say:
: 
:    for (<$iter>) { ... }                # whole thing ($iter.more)
:    for ( ($iter.more)[0..4] ) { ... }   # lazy evaluation
:    for my $n (<$iter>[0..4]) { ... }    # same thing

It's possible we're thinking of iterators wrong here.  Perhaps
iterators should typically be stored in @iter, not $iter.  Then it's
pretty obvious that

    for (@iter) { }

iterates, because it's in a list context.  I think iterator magic
always works in list context, and never in scalar.  What we have to get
away from is the notion that lists are always flattened immediately.
They're not, unless you use unary * to force it.  Most lists will be
passed around notionally in Perl 6, not physically.  That will allow

    @a || @b

to work regardless of whether it's in a scalar or list context.

Larry

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About