Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Appeler une méthode inconnue

2 réponses
Avatar
Jean-Michel Caricand
Bonsoir,

Je cherche une solution pour le problème suivant. J'ai un objet A possédant
les méthodes f1 et f2. J'aimerais trier une liste de références sur des
objets de type A sur la valeur retournée par f1 ou par f2. Voici mon code :

...

$choix = "f1";

my @liste2 = sort { $a->$f1 cmp $b->$f1 } @liste1;

...

Evidemment cela ne fonctionne pas. Existe-t-il une solution propre pour
résoudre mon problème ?

Merci.

2 réponses

Avatar
Jean-Michel Caricand
Jean-Michel Caricand wrote:

Bonsoir,

Je cherche une solution pour le problème suivant. J'ai un objet A
possédant les méthodes f1 et f2. J'aimerais trier une liste de références
sur des objets de type A sur la valeur retournée par f1 ou par f2. Voici
mon code :

...

$choix = "f1";

my @liste2 = sort { $a->$f1 cmp $b->$f1 } @liste1;

...

Evidemment cela ne fonctionne pas. Existe-t-il une solution propre pour
résoudre mon problème ?

Merci.


J'ai fait une erreur dans mon code :-(

$choix = "f1";

my @liste2 = sort { $a->$choix cmp $b->$choix } @liste1;

Excusez moi.

Avatar
Jean-Baptiste Mazon
Jean-Michel Caricand writes:
Je cherche une solution pour le problème suivant. J'ai un objet A
possédant les méthodes f1 et f2. J'aimerais trier une liste de références
sur des objets de type A sur la valeur retournée par f1 ou par f2. Voici
mon code :

$choix = "f1";


my @liste2 = sort { $a->$choix cmp $b->$choix } @liste1;


A un détail près, ça marche chez moi. Il m'a toutefois été nécessaire
de me livrer à une bonne dose d'extrapolation. Le bon usage demande
que l'exemple de problème soit concis, certes, mais suffisant pour
tourner de lui-même. Les détails de pourquoi ça ne marche pas ne sont
pas de trop non plus (messages d'erreur, par exemple).

Déclarer un nom de fonction (ici méthode) dans une variable, ça
s'appelle une référence symbolique. C'est déconseillé, obsolète, à
éviter pour tout un tas de (bonnes) raisons, mais c'est encore censé
marcher. Mais pour que Perl la retrouve, il lui faut quand même le
nom du package où la trouver. Supposant "A", ça nous donne:

$choix = 'A::f1';

Débarrassons-nous tout de suite de la référence symbolique, dans notre
cas ça ne change presque rien au code:

$choix = &A::f1;

Bon.

Malheureusement, cette manière de faire passe outre le dispatching:
si quelqu'un dérive A et redéfinit f1, c'est malgré tout A::f1 qui se
fera appeler.

Pour dispatcher et sur la méthode et sur la classe... je ne connais
pas de solution Perl 5 qui reste concise. Il y a bien eval, mais
c'est zéro en performances comme en maintenabilité. Si quelqu'un a
une meilleure idée, je suis moi aussi preneur.

Un peu de code autosuffisant pour illustrer le tout:

#! perl -l

package A;
sub key1 { substr ${$_[0]}, 0, 1 } # premiere lettre
sub key2 { substr ${$_[0]}, -1 } # derniere lettre
sub new { bless $_[1] }

package main;

@_ = map new A($_), qw(ceci est une liste de quelques mots);

print 'Tri par première lettre:';
print $$_ for sort { $a->key1 cmp $b->key1 } @_;

print 'Tri par dernière lettre:';
print $$_ for sort { $a->key2 cmp $b->key2 } @_;

print 'Tri par référence symbolique:'; # mais c'est Mal
$_ = 'A::key1';
print $$_ for sort { $a->$_ cmp $b->$_ } @_;

print 'Tri paramétré:';
$_ = &A::key1;
print $$_ for sort { $_->($a) cmp $_->($b) } @_;


Les syntaxes utilisées pour les tris par référence sont
interchangeables. En l'occurrence, je préfère la seconde, qui
illustre mieux où le dispatching a effectivement lieu.