>>>>> "GNP" == Gregor N Purdy <[EMAIL PROTECTED]> writes:

  GNP> The Schwartzian is the usual way, of course:

  GNP>   map { $_->[1] }
  GNP>   sort { $^a[0] <=> $^b[0] }
  GNP>   map { [ $_.foo('bar').compute, $_ ] }
  GNP>   @unsorted;

and the GRT is another. 

let stick my nose in here. sorting is really composed of 3 parts,
extracting keys, comparing them and then getting back the records in
sorted order. the p5 sort block idioms require duplicating the extract
code and usually a binary operator. the GRT eliminates the binary
operator as it uses the default string compare in sort but it still
requires key extraction and then record extraction (similar to the first
map (last executed) in the ST.

  GNP> But we really aren't being concise here.

  GNP> (Aside) I wonder if there will be a new Perl 6 idiom to replace this
  GNP> using properties, something like this:

  GNP>   map { $_.really }
  GNP>   sort : numerically
  GNP>   map { $_.foo('bar').compute but really($_) }
  GNP>   @unsorted;

  GNP> or:

  GNP>   @unsorted
  GNP>     ==> map { $_.foo('bar').compute but really($_) }
  GNP>     ==> sort : numerically
  GNP>     ==> map { $_.really };

  GNP> But we *still* aren't concise.

that is the problem. the merging of the extracted key (in the ST or GRT)
with the record and the extraction of the record need to be hidden as
that is common code.

  GNP> Maybe we should have a two-block sort? The second block gives the
  GNP> transform to apply to the elements before applying the comparison
  GNP> block:

  GNP>   sort { $^a <=> $^b } { $_.foo('bar').compute } @unsorted;

duplicate args again.

  GNP> Or maybe even something like this:

  GNP>   sort :numerically :as { $^a.foo('bar').compute } @unsorted;

that looks best but how do you replace the :numerically comparison with
say a unicode aware string compare?

i have been working on a Sort::GRT in my head (finally!) and have some
ideas.

first, key extraction should work on $_ which is set for each element of
the unsorted list so there is no need for $^a. also how can you extract
multiple keys? and each key needs a ascending/descending option. and
each key needs a type so it can be compared correctly.

so here is a (very rough and probably broken) syntax idea building on
that:

sort :key { :descend :string .foo('bar').substr( 10, 3) }
     :key {          :int .foo('baz') }
     :key {          :float .foo('amount') } @unsorted ;

sort takes a list of :key's which each has a block (or whatever) that
specifies the key type, ordering and extraction code (that works on the
record in $_). the extraction code is in a block in itself so you can
declare lexicals and use multiple statements. the last value (in list
context) is the key. this is so you can do (p5 style) /foo(\d+)bar/ and
extract that digit string as the key.

side note: i was pondering the problem of where two different keys have
to be extracted from nearby places deep in a nested record
structure. this means duplicate code will be used to get into the deep
part. in my module, i was planning to allow a 'pre-extraction' piece of
code to be used and the value (e.g. a ref to the deep part) stored in a
lexical which can be used later in both key extractions. i don't know
any way to do that with the above syntax. there has to be a larger block
around all the :key's to allow something like that here. the p5 module
will be wrapping all the key extract code in a block so this would work
there.

internally, each record has its keys extracted and they are merged using
the GRT or ST or similar. in either case the record must be attached
(via a pointer or appended or some other way) to the merged key. the
keys are sorted and then the attached records are grabbed back and
returned. sorting in place can be done too.

what is good about the above syntax is that it removes all the common
code, removes the binary operator (order and type is all that matters)
and allows for a simple way to express multiple key extractions.

it can be implemented internally in c to be far faster than any perl or
parrot level code could do. the biggest hurdle i see is proper support
for unicode stuff. maybe another key attribute would be the collating
name? how this affects internal sorting is a question. can you generate
a merged key with numbers, ascii and unicode strings that will sort with
simple string compares? maybe the unicode extraction has to do a char by
char conversions to (32 bit?) integers using the collate sequence and
those numbers can easily be merged and sorted. note that only the
extracted key text needs to be converted so that shouldn't be too
expensive. so it may look like this:

sort :key { :descend :string :collate('iso_some_country') 
                          .foo('bar').substr( 10, 3) }
     :key {          :int .foo('baz') } @unsorted ;

what is nice about that is that each key could have its own collate
type. the :string attribute could be optional since the :collate implies
a string.

just trying to sort things out,

uri

-- 
Uri Guttman  ------  [EMAIL PROTECTED]  -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs  ----------------------------  http://jobs.perl.org

Reply via email to