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

Containers

7 views
Skip to first unread message

Aaron Sherman

unread,
Jul 11, 2006, 10:06:32 AM7/11/06
to Perl6 Language List
S02 and S06 discuss containers quite a bit. They say things like:

"The is NAME (DATA) syntax defines traits on containers and
subroutines" -S06

"A variable object may itself be bound to a container type that
specifies how the container works without necessarily specifying
what kinds of things it contains." -S02

>From this, I gather that it is our intention that containers have common
behaviors. In working on the Functions document (nominally S29), I've
come across some functions (such as C<each>, defined in S03), which are
not tied to specific container types, and probably want to be defined in
terms of the common container class.

Is it OK for me to arm-wave a C<Container> class which can stand in for
any container type? For example:

our List multi Container::each(Container *@containers)

Thoughts? Bad plan? I understand that there's some ambiguity here... it
might even be that Container is a role, not a class, or might be an
arm-wavy thing that abstracts some implementation details. I'm not
concerned about that just yet, I just need something to call these
things. Otherwise I have to put one definition for each of these
functions into the section for each type of container (too many
eaches...). I don't even have a section for things like Seq and Buf yet,
and I'd rather not if I don't have to.

--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"We had some good machines, but they don't work no more." -Shriekback


Jordan Kanter

unread,
Jul 11, 2006, 10:28:04 AM7/11/06
to perl6-l...@perl.org
I was having that problem too going over S09. It seems like we need to get
the glossary together like Uri was saying that we can have a controlled
language for creating the documents. If we dont have one already, I suggest
we start one.

Jordan

Aaron Sherman

unread,
Jul 11, 2006, 12:13:41 PM7/11/06
to Perl6 Language List
On Tue, 2006-07-11 at 10:06 -0400, Aaron Sherman wrote:
> For example:
>
> our List multi Container::each(Container *@containers)

In thinking about each, I've come across an interesting need. I wrote
this example:

for each(=<>; 1..*) -> ($line, $lineno) {
say "$lineno: $line";
}

Which is obviously an infinite loop. You could re-write that:

for each(=<>; 1..*) -> ($line, $lineno) {
$line err last;
say "$lineno: $line";
}

But would it be reasonable to also provide a named-only parameter to
each for that purpose?

our List multi Container::each(Bool :$stop, Container *@containers)

So that:

for each(:stop, =<>; 1..*) -> ($line, $lineno) {
say "$lineno: $line";
}

would only iterate until one of the containers was exhausted (in this
case, the filehandle).

Should this be added? Should zip have the same modifier?

--
Aaron Sherman <a...@ajs.com>
Do you find yourself thinking Unicode has too many crosses? ✙✚✛✜✝✞✟✠☦☨☩†


Aaron Sherman

unread,
Jul 11, 2006, 12:28:25 PM7/11/06
to Jordan Kanter, perl6-l...@perl.org
On Tue, 2006-07-11 at 09:28 -0500, Jordan Kanter wrote:
> I was having that problem too going over S09. It seems like we need to get
> the glossary together like Uri was saying that we can have a controlled
> language for creating the documents. If we dont have one already, I suggest
> we start one.

Actually, I don't think we disagree on terminology (nor do the
synopses). The problem is that the types, as listed, don't fully fit the
terminology. This is to be expected, since we haven't fully fleshed out
the type tree yet.

That's why I said that Container might not be as real as it sounds. It
could just be a role, since many "container-like things" aren't going to
fall neatly into the Object -> Container -> Array/Hash type tree. Buf is
probably the best example of this, as a Buf is really a sort of scalar
with containerish behavior. Something like, "class Buf is Scalar, does
Container". Which really blows some assumptions that I'm willing to bet
many people will make.

--
Aaron Sherman <a...@ajs.com>

Trey Harris

unread,
Jul 11, 2006, 12:53:55 PM7/11/06
to Aaron Sherman, Perl6 Language List
In a message dated Tue, 11 Jul 2006, Aaron Sherman writes:
> But would it be reasonable to also provide a named-only parameter to
> each for that purpose?
>
> our List multi Container::each(Bool :$stop, Container *@containers)
>
> So that:
>
> for each(:stop, =<>; 1..*) -> ($line, $lineno) {
> say "$lineno: $line";
> }
>
> would only iterate until one of the containers was exhausted (in this
> case, the filehandle).
>
> Should this be added? Should zip have the same modifier?

It sounds reasonable to me, but :stop reads badly. Maybe C<:strictly>?
Maybe it's not a function of a flag to each, but a marking that certain
lists should be tapped non-exhaustively:

for each(=<>; :with(1..*)) -> ($line, $lineno)

Where "with" is almost certainly the wrong word. That way, you could
write:

for each(@queue1; @queue2; :with(1..*)) -> $t1, $t2, $job_num {
say "Running job #$job_num";
$proc1.run_task($t1); # Can deal with $t1 being undef
$proc2.run_task($t2); # Ditto with $t2
}

And you'll eat the rest of @queue1 or @queue2's elements even if they
don't match up exactly.

This all makes me wonder if there's any problem with mixing and matching
these loop modifying subs:

for each(roundrobin(@queue1; @queue2); :with(1..*)) -> $task, $job_num {
say "Running task {$task.id}(#$job_no)";
$task.run(:$job_num);
}

I hope not.

Trey

Aaron Sherman

unread,
Jul 11, 2006, 3:20:47 PM7/11/06
to Trey Harris, Perl6 Language List
On Tue, 2006-07-11 at 09:53 -0700, Trey Harris wrote:
> In a message dated Tue, 11 Jul 2006, Aaron Sherman writes:
> > But would it be reasonable to also provide a named-only parameter to
> > each for that purpose?

> It sounds reasonable to me, but :stop reads badly. Maybe C<:strictly>?

> Maybe it's not a function of a flag to each, but a marking that certain
> lists should be tapped non-exhaustively:

:stop wasn't a great choice, but :with is going to be complicated. I
don't THINK there's such a thing as a named slurpy, so:

> for each(=<>; :with(1..*)) -> ($line, $lineno)

would have to be:

for each(=<>, :with(1..*))

with the signature:

(Container :@with, Container *@containers)

I think....

But I don't think that will do, because it fails when you don't know
WHICH list would be the longest (or you have to specify them all
as :with, and that's rather counter-intuitive). Perhaps a stand-alone
adverb, :parity makes more sense.

Unless there's an obvious problem with it, let's go with :parity for
now, and we can change it if its usage becomes confusing.

> This all makes me wonder if there's any problem with mixing and matching
> these loop modifying subs:
>
> for each(roundrobin(@queue1; @queue2); :with(1..*)) -> $task, $job_num {
> say "Running task {$task.id}(#$job_no)";
> $task.run(:$job_num);
> }
>
> I hope not.

This makes me re-think each a bit... it might have to return an
iterator:

our Iterator multi Container::each (Bool :$parity , Container *@containers )

Given that, you could string eaches all you like, but otherwise it's not
terribly useful.

Trey Harris

unread,
Jul 11, 2006, 3:50:01 PM7/11/06
to Aaron Sherman, Perl6 Language List
In a message dated Tue, 11 Jul 2006, Aaron Sherman writes:
> On Tue, 2006-07-11 at 09:53 -0700, Trey Harris wrote:
>> It sounds reasonable to me, but :stop reads badly. Maybe C<:strictly>?
>> Maybe it's not a function of a flag to each, but a marking that certain
>> lists should be tapped non-exhaustively:
>
> :stop wasn't a great choice, but :with is going to be complicated. I
> don't THINK there's such a thing as a named slurpy, so:
>
>> for each(=<>; :with(1..*)) -> ($line, $lineno)
>
> would have to be:
>
> for each(=<>, :with(1..*))
>
> with the signature:
>
> (Container :@with, Container *@containers)
>
> I think....
>
> But I don't think that will do, because it fails when you don't know
> WHICH list would be the longest (or you have to specify them all
> as :with, and that's rather counter-intuitive). Perhaps a stand-alone
> adverb, :parity makes more sense.

I don't understand how the word "parity" is being used here... It's not
in the mathematical sense of "even vs. odd", nor in the telecomm sense of
bit-counting (since one would want to stop if one out of four iterators
stopped generating, but also if two out of four did). In the colloquial
sense of parity meaning "equality amongst peers", perhaps it makes more
sense, but it's a rather overloaded an poorly-understood word, IMHO.

> Unless there's an obvious problem with it, let's go with :parity for
> now, and we can change it if its usage becomes confusing.

I think both are needed, somehow. The default behavior of each should be
as before (returning undef as necessary). If the boolean switch (:stop,
:parity, whatever) is set, then each should stop generating as soon as any
argument stops generating. I'm not denying that need. But I'm saying
that there is also a need for a mixed-case usage.

This is another one of those cases where you have to have at least three
items to see a difference, at (0|1|2)-ary the semantic differences
collapse.

One would like to be able to say all of "stop once this iterator runs out"
(these adverb names are intentionally awful):

for each(:stop_on_exhaustion(=<>), @line_id_cookies; 1..*)

"Stop when anything besides this iterator runs out":

for each(=<>; @lines_to_merge; :attach_as_needed(1..*))

"Stop when any iterator runs out":

for each(:stop, @subjects; @objects; @verbs) -> $s, $o, $v

>> This all makes me wonder if there's any problem with mixing and matching
>> these loop modifying subs:
>>
>> for each(roundrobin(@queue1; @queue2); :with(1..*)) -> $task, $job_num {
>> say "Running task {$task.id}(#$job_no)";
>> $task.run(:$job_num);
>> }
>>
>> I hope not.
>
> This makes me re-think each a bit... it might have to return an
> iterator:
>
> our Iterator multi Container::each (Bool :$parity , Container *@containers )
>
> Given that, you could string eaches all you like, but otherwise it's not
> terribly useful.

They need to chain and nest intelligently.

Trey

Aaron Sherman

unread,
Jul 11, 2006, 4:22:12 PM7/11/06
to Trey Harris, Perl6 Language List
On Tue, 2006-07-11 at 12:50 -0700, Trey Harris wrote:

> > But I don't think that will do, because it fails when you don't know
> > WHICH list would be the longest (or you have to specify them all
> > as :with, and that's rather counter-intuitive). Perhaps a stand-alone
> > adverb, :parity makes more sense.
>
> I don't understand how the word "parity" is being used here... It's not
> in the mathematical sense of "even vs. odd", nor in the telecomm sense of
> bit-counting (since one would want to stop if one out of four iterators
> stopped generating, but also if two out of four did). In the colloquial
> sense of parity meaning "equality amongst peers", perhaps it makes more
> sense, but it's a rather overloaded an poorly-understood word, IMHO.

Yeah, I see your problem. I WAS using the "equality amongst peers"
definition, but you're probably right that there's too much baggage.

Having read and digested the rest of your mail and your comments on IRC,
let me propose (as I did on IRC before you had to run):

zip(:fewest, @a;@b;@c); # Until one runs out
zip(:finite, @a;@b;@c); # Stop if only known-infinite ranges are left
roundrobin(:most, @a;@b;@c); # Include undefs until all arrays empty
zip(@a;@b:fewest;@c); # empty @b, then stop.
zip(@a:fewest;@b;@c:fewest); # stop when non - @b is empty
zip(@a:fewest;@b:fewest;@c:fewest); # Same as stand-alone :fewest
roundrobin(@a;@b:most;@c); # fill in undefs for @b until @a,@c empty
roundrobin(@a:most;@b;@c:most); # fill in undefs for all but @b
roundrobin(@a:most;@b:most;@c:most); # Same as stand-alone :most

I think that covers all of the bases that I, you and Larry proposed.

I'm still not clear on how :fewest and :most modify a container, but I'm
convinced that once I make sense of it, there will be other ways in
which I want to use that modifier.

Aaron Sherman

unread,
Jul 11, 2006, 4:25:29 PM7/11/06
to Trey Harris, Perl6 Language List
On Tue, 2006-07-11 at 16:22 -0400, Aaron Sherman wrote:

> zip(:fewest, @a;@b;@c); # Until one runs out

Once again, I missed some Larry magic. He already selected ":shortest"
for this, so I guess on roundrobin, it's ":longest"... ignore my
choices.

I think just like Larry, but 1,000 times slower and less patient ;-)

0 new messages