develooper Front page | perl.perl5.porters | Postings from July 2021

Re: Elevator pitch, deprecating $a/$b sort globals by using sub{}

Thread Previous | Thread Next
Darren Duncan
July 7, 2021 11:07
Re: Elevator pitch, deprecating $a/$b sort globals by using sub{}
Message ID:
On 2021-07-06 1:32 p.m., Smylers wrote:
> That is, a list of pairs of type/direction indicators and
> keys, followed by the list of things to sort.
> But there isn't really a syntax for that which fits in with any other
> core function:
> • It needs two separate lists: the spec list, then the list of items. I
>    don't think there's any other core function that handles multiple
>    lists.
> • It needs (potentially) multiple blocks. I've put explicit sub-s in the
>    example above. Core functions taking a block don't require the sub
>    prefix, but only take one block, in a known place (and directly as an
>    arg, not nested inside an array).
> • It needs a mini-language or options syntax for specifying the
>    comparison type and direction. There are core functions with something
>    similar, but none that directly seem to apply here:
>> ... to me it feels like we're now creating a *different* set of special
>> case syntax for sort, to eliminate the current special-case syntax ($a, $b).
>> What else might re-use this syntax?

It seems to me there is a MUCH simpler and more generic solution here.  Once one 
even starts thinking about a special mini-language we should just skip that and 
just use Perl.

Here is a complete pure-Perl implementation of my proposal:

   sub newsort {
     my ($ord_func, $key_func, $list) = @_;
     return [
       map { $_->[1] }
       sort { $ord_func->($a->[0], $b->[0]) }
       map { [$key_func->($_), $_] }

You use it like this:

   $sorted = newsort( sub { $_[0] cmp $_[1] }, sub { $_[0] }, $unsorted );

That sample call just emulates the behavior of normal built-in sort, and doing 
any other kind of sort is an exercise left for the reader.

The key feature here is that all the special logic is in the form of ordinary 
sub references, aka regular Perl code, which can have as complicated logic as 
the users want, no special sub-language.

This provides the desired algorithmic efficiency such that the logic to produce 
a total sort key is just done once per input element and cached.

Hypothetically if the $key_func always produced keys of some kind of 
standardized format, such as an arrayref of elements to compare pairwise (such 
as [$_->{name}, $_->{age}] etc, then the user-provided $ord_func could be 
skipped entirely because a particular generic system-defined sort function would 
be implicitly used which worked with the standardized format.  But that would 
assume a language where every array element's type could be appropriately 
detected and the right sort function automatically be used.  For arrayrefs is 
the simple per-element pairwise, for text cmp(), and so on.

Further to the prior paragraph, if that would work, then this infrastructure 
could also be reused for implementing an always-sorted collection similar to a 
SQL database table on possibly multiple columns.  The only aspect that is 
user-defined in either case is the $key_func that derives from each collection 
element a normalized format, and the actual ordering logic is built-in only.

-- Darren Duncan

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About