[Munich-pm] sort mit curried function

Harald Joerg harald.joerg at ts.fujitsu.com
Mo Nov 19 03:40:33 PST 2012


Hallo Robert,

Dass Deine Überlegungen nicht funktionieren, liegt daran, dass
sort SUBNAME LIST syntaktisch etwas "eingeschränkt" ist.

Es geht aber, mit einfacherem bykey, wie folgt:

----------------------------------------------------------------------
#!/usr/bin/perl -w

use strict;

my @liste = ({ x => 1, y => 4}, {x => 3, y => 2});

foreach my $h (sort {bykey('x')} @liste){
     print $h->{x}, $h->{y}, "\n";
}

sub bykey {
     my $key = shift;

     return($a->{$key} <=> $b->{$key});
}
----------------------------------------------------------------------

   * Anstelle von sort SUBNAME LIST verwende ich sort BLOCK LIST,
     das frisst der Parser leichter.

   * In bykey sind $a und $b direkt verfügbar, das sind package globals
     (@Marek: Die muss man also nicht übergeben). Der Code ist nicht
     reentrant, es wäre also unklug, innerhalb von bykey nochmal einen
     sort-Aufruf zu haben (ginge auch, aber nur über sort mit Prototypes).

     Es ist aber nicht nötig, eine eigene Subroutine zu erzeugen.
     (@Roderich: Geht nicht - gibt's nicht :))
-- 
Cheers,
haj



"Robert C. Helling" <helling at lmu.de> writes:

> Hallo,
>
> ich stehe grade mal wieder auf dem Schlauch. Ich habe eine Liste mit 
> Hashreferenzen, wobei die Hashes mehrere Felder vom gleichen Typ haben. 
> Nun moechte ich gerne die Liste sortieren anhand jeweils eines Feldes des 
> Hashes. Die Vergleichsfunktion ist etwas kompliziert. Daher will ich sie 
> nicht fuer jedes Hashfeld neu schreiben, sondern mach lieber eine 
> gemeinsame Vergleichsfunktion, die den Namen des Feldes bekommt und dann 
> entsprechend gecurried wird. Schematisch wie in diesem Beispiel:
>
> #!/usr/bin/perl -w
>
> use strict;
>
> my @liste = ({ x => 1, y => 4}, {x => 3, y => 2});
>
>
> my $byx = &bykey('x');
>
> foreach my $h (sort $byx @liste){
>      print $h->{x}, $h->{y}, "\n";
> }
>
> sub bykey {
>      my $key = shift;
>
>      return(sub {$a->{$key} <=> $b->{$key}});
> }
>
>
> Das funktioniert so. Meine Frage ist nun: Wie komme ich ohne die 
> Dummyvariable $byx aus? Ich habe zB schon probiert
>
> foreach my $h (sort &&bykey('x') @liste){
>
> aber das gibt einen Syntaxerror. Auch aehnliche Versionen mit weniger &'s 
> und mehr oder wenigen Klammern verschiedenen Typs habe ich probiert, aber 
> nichts davon funktionierte.
>
> Wer erleuchtet mich?
>
> Viele Gruesse
> Robert


Mehr Informationen über die Mailingliste Munich-pm