On 10/5/05, Damian Conway <[EMAIL PROTECTED]> wrote:
> Luke wrote:
> > I'm just wondering why you feel that we need to be so careful.
>
> Because I can think of at least three reasonable and useful default behaviours
> for zipping lists of differing lengths:
>
> # Minimal (stop at first exhausted list)...
> for @names ¥ @addresses -> $name, $addr {
> ...
> }
>
>
> # Maximal (insert undefs for exhausted lists)...
> for @finishers ¥ (10..1 :by(-1)) -> $name, $score {
> $score err next;
> ...
> }
>
>
> # Congealed (ignore exhausted lists)...
> for @queue1 ¥ @queue2 -> $server {
> ...
> }
>
> Which means that there will be people who expect each of those to *be* the
> default behaviour for unbalanced lists.
Perhaps that makes sense. That certainly makes sense for other kinds
of constructs. Something makes me think that this is a little
different. Whenever somebody asks what "Y" is on #perl6, and I tell
them that it interleaves two lists, a follow-up question is *always*
"what does it do when the lists are unbalanced." Now, that may just
be a behavior of #perl6ers, but I'm extrapolating. It means that
there isn't an assumption, and if they weren't #perl6ers, they'd RTFM
about it.
When I learned Haskell and saw zip, I asked the very same question[1].
I was about as comfortable writing Haskell at that point as beginning
programmers are with writing Perl, but it still took me about ten
seconds to write a test program to find out. The rest of Perl doesn't
trade a reasonable default behavior for an error, even if it *might*
be surprising the first time you use it. It doesn't take people long
to discover that kind of error and never make that mistake again.
If we make zip return a list of tuples rather than an interleaved
list, we could eliminate the final 1/3 of those errors above using the
typechecker. That would make the for look like this:
for @a Y @b -> ($a, $b) {...}
An important property of that is the well-typedness of the construct.
With the current zip semantics:
my A @a;
my B @b;
for @a Y @b -> $a, $b {
# $a has type A (+) B
# $b has type A (+) B
}
With tuple:
my A @a;
my B @b;
for @a Y @b -> ($a, $b) {
# $a has type A
# $b has type B
}
Which is more correct. No... it's just correct, no superlative
needed. It also keeps things like this from happening:
for @a Y @b -> $a, $b {
say "$a ; $b"
}
# a1 b1
# a2 b2
# a3 b3
# ...
"Oh, I need a count," says the user:
for @a Y @b Y 0... -> $a, $b { # oops, forgot to add $index
say "$a ; $b"
}
# a1 b1
# 0 a2
# b2 1
# ...
Luke
[1] But I didn't need to. The signature told me everything:
zip :: [a] -> [b] -> [(a,b)]
It *has* to stop at the shortest one, because it has no idea how to
create a "b" unless I tell it one. If it took the longest, the
signature would have looked like:
zip :: [a] -> [b] -> [(Maybe a, Maybe b)]
Anyway, that's just more of the usual Haskell praise.