E 'possibile fare riferimento simbolicamente un modulo di base Perl?
-
05-10-2019 - |
Domanda
So che avrei potuto facilmente fare qualcosa di simile
sub sin {
sin($_[0]);
}
e simbolicamente di riferimento che per ogni funzione che ho bisogno di Symb ref, ma mi piacerebbe solo sapere se c'è un modo per fare qualcosa di simile
{$foo}(123);
vs.
&{$foo}(123);
che funziona, ma non per le funzioni fondamentali.
Grazie.
Soluzione
Per quanto ne sappia no, non puoi farlo. Per motivi di prestazioni, funzioni CORE
mai guardare la tabella dei simboli a meno che una funzione di CORE::GLOBAL
equivalente è stato dichiarato in fase di compilazione. Purtroppo, si deve scrivere quella funzione CORE::GLOBAL
e farlo giusto per simulare le convenzioni di chiamata della funzione reale. Alcune funzioni CORE
non possono essere interamente riprodotte senza hack massiccia, print
e open
per esempio. Dal momento che è globale CORE::GLOBAL
un tutto il codice e tutto il codice libreria di effetti bisogna essere sicuri di ottenere che esattamente diritto o molto difficile da errori di debug. Alcuni moduli, come Autodie , andare a grandi lunghezze per avvolgere funzioni principali.
Ma qui, mi permetta di mostrare dove l'armadietto pistola e le munizioni sono ...
my @return = eval "$function(\@args)";
... Naturalmente, questo è un enorme sicurezza e manutenibilità foro. Non farlo.
Altri suggerimenti
Se leggo questa domanda SO correttamente, non si può prendere un riferimento a una funzione built-in. Ho il sospetto che le difficoltà analoghe vi impediranno di invocare built-in utilizzando i riferimenti simbolici.
Per quanto riguarda l'uso di riferimenti simbolici per il codice invoke, vorrei suggerire che si utilizza una tabella di spedizione, invece. Ad esempio:
use strict;
use warnings;
sub sin_deg { sin $_[0] * atan2(1, 1) / 45 }
my %dt = (
sin_deg => \&sin_deg,
attack => sub { print "Attacking: @_\n" },
);
print $dt{sin_deg}->(60), "\n";
$dt{attack}->(1, 2, 3);
Sembra che è necessario sostituire le funzioni di base in fase di compilazione, e poi si può giocherellare con loro. Mi piace l'hash spedizione (o scalare) approccio migliore, però.
use strict;
use warnings;
our $s;
BEGIN {
*CORE::GLOBAL::sin= sub { sin($_[0])*2 };
*CORE::GLOBAL::cos= sub { cos($_[0])*2 };
our $s= *CORE::GLOBAL::sin;
}
*CORE::GLOBAL::sin= *CORE::GLOBAL::cos;
print sin(0.01)."\n";
print $s->(0.01)."\n";