Jonathan Lang writes:
> > We already have that.  It's spelled:
> > 
> >     routine [EMAIL PROTECTED];
> > 
> > Or
> > 
> >     routine * <== @x;
> 
> Then you've got your solution:
> 
>   @sorted = sort {infix:<=> * map {$_.foo('bar').compute}, $^a, $^b }
>             @unsorted; 
> 
> or
> 
>   @sorted = sort {($^a, $^b) ==>
>                   map {$_.foo('bar').compute} ==>
>                   infix:<=> * } @unsorted; 

No, I don't think we do.  Uri's given some good points in this thread
about specifying what you want out of the sort, instead of some
arbitrary callback interface.

But it needs some major syntax work so it can feel more like it's a part
of the language instead of a library function.  Not, mind, that I think
Perl's syntax needs to be changed at all to accommodate.

I'm thinking that C<sort> might take a list of closures or pairs (with
the value being a closure).  I'm still not sure how that separates from
the data to be sorted, but it's probably related to the problem of how
C<for> works in declaration.

The return value of each closure is dispatched into some sort of generic
<=>, hopefully one that blows up if its arguments are of different
types[1]. That way if you have a method that always returns a number,
you can just leave it alone.  Otherwise you're expected to prefix with
the approprate contextifier.

For example:

    sort { .foo('bar').compute }, desc => { ~.baz }, @data;
    #     ascending by default              string compares

Pairs don't exactly seem fit here.  Maybe we're supposed to think of
these these closures as higher-level 'extractors', and therefore attach
properties to them:

    sort { .foo('bar').compute }, { ~.baz } but descending, @data;

Or even something on the value that tells <=> to negate whatever it
returns:

    sort { .foo('bar').compute }, { ~.baz but swap }, @data;

That's starting to expose implementation again, though.

Moving a different direction now.  Instead of being honest and saying
that sort does each of these comparisons until one of them is nonzero,
let's pretend that it sorts with respect to the first comparison and
feeds the lists of equal elements into the second comparison, etc.

Sort might then look like:

    sub sort (?&extract, ?&next, [EMAIL PROTECTED])

And our example turns into:

    sort { .foo('bar').compute } 
         { reverse sort { ~.baz } [EMAIL PROTECTED] } 
         [EMAIL PROTECTED];

That hurts, especially when there are more than two keys.  I'd really
like to do that with the piping operators instead of nested closures,
but that screws with the simple case.

There might be even more ways of looking at this that would result in
more novel syntaxes.  Brainstorming required.

Luke

[1] There's something to be said for a generic comparison, but not one
that blows up.  Mostly because certain containers want their elements to
be well ordered.  But we could just as easily say that elements that
aren't intercompatible with the short-tempered <=> aren't allowed in
said containers.

Reply via email to