2 votes

Expliquez cette sorcellerie ! !! (en Perl, avec Moose et namespace::autoclean)

Ces jours-ci, je travaille sur un projet qui utilise Perl et Moose. Je comprends que Moose est construit sur MOP. Je ne suis pas trop familier avec MOP, et j'ai rencontré quelque chose que je ne comprends pas, et j'aurais besoin d'une explication théorique. Voici le module namespace::autoclean de la documentation :

SYNOPSIS
    package Foo;
    use namespace::autoclean;
    use Some::Package qw/imported_function/;

    sub bar { imported_function('stuff') }

    # later on:
    Foo->bar;               # works
    Foo->imported_function; # will fail. imported_function got cleaned after compilation

Ainsi, avant que je n'utilise Moose, la façon d'appeler une méthode sur un objet était la suivante : l'interpréteur Perl cherchait cette méthode dans la table des symboles du paquetage dans lequel votre objet était béni (puis, si elle n'était pas trouvée, considérait @ISA l'héritage et autres). La façon dont il appelle une fonction importée à partir du paquetage est la suivante : il recherche le nom de la fonction dans la table des symboles du paquetage. Pour autant que j'en sois conscient à ce jour, cela signifie que la table des symboles est la même, quelle que soit la façon dont elle est utilisée, donc ce comportement devrait être impossible.

Ma première inspection de la source n'a pas été productive. En gros, qu'est-ce qui est différent dans l'utilisation de Moose, MOP, et namespace::autoclean, pour que ce genre d'artifice devienne possible ?

ed. Pour être particulièrement clair, si je devais remplacer use namespace::autoclean avec

CHECK { undef *Foo::imported_function }

alors le Foo->bar; décrit dans la documentation se planterait, car Foo->bar ne sait pas où trouver imported_function .

3voto

ikegami Points 133140

C'est en fait assez simple. Pour

some_sub()

some_sub est résolu au moment de la compilation. Pour

$o->some_method()

some_method est résolu au moment de l'exécution. Cela ne peut pas être fait au moment de la compilation, car cela dépend de la valeur du paramètre $o .

1voto

Borodin Points 52478

Il n'y a rien ici qui soit hors norme. La ligne

use Some::Package qw/imported_function/;

importations imported_function dans le paquet actuel, donc Foo::imported_function est la même sous-routine que Some::Package::imported_function . Cela suppose que Some::Package hérite de Exporter pour effectuer les manipulations nécessaires dans les tables de symboles.

Les appels sont des appels de méthode, donc Foo->bar est la même chose que Foo::bar('Foo') . La seule chose spéciale ici est que la magie qui a été faite par la import de la fonction Exporter est annulée à la fin du temps de compilation par namespace::autoclean .

Je n'ai pas regardé le code de ce module, mais puisque la table des symboles d'un paquet est juste un hash (connu sous le nom de cachette pour table de hachage des symboles ), il serait facile de préserver son état à un moment donné et de le restaurer par la suite. Je dirais donc namespace::autoclean prend un instantané de la table des symboles lorsqu'elle est chargée et restaure cet état à la fin de la compilation. Ceci peut être fait de manière pratique dans un CHECK bloc qui se comporte comme un BEGIN mais il est exécuté à la fin de la compilation et avant le début de l'exécution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X