Potete fornire qualche esempio in cui l'utilizzo di eval EXPR
è davvero necessario? Chiedo perché è generalmente scoraggiato.Ci sono dei casi d'uso in cui l'eval di stringa è necessario in Perl?
risposta
Parecchio anni fa, ho scritto un generatore di siti Web statici che utilizzava Perl (< - interessante il fatto che il mio correttore ortografico suggerisce "Pericolo" in sostituzione di quello) come linguaggio di scripting. Permetteva all'utente di inserire informazioni su diversi livelli di una gerarchia: il primo al mercato era per un cimitero in cui si avevano clienti (clienti paganti) che possedevano memoriali (per i defunti, ovviamente).
Aveva una GUI dove siete entrati variabili quali (tremare le mie capacità grafiche qui):
+------------+----------------------------+
| ClientName | Pax Diablo |
+------------+----------------------------+
| Address | 666 Hades St, Washinton DC |
+------------+----------------------------+
e le variabili di immagine pure.
Inoltre, per ogni mercato (come il citato), c'era uno script di controllo che fondamentalmente eseguiva ed elaborava ogni record a più livelli gerarchici per generare il contenuto statico. Prima di allora, il programma aveva girato tutte queste variabili in cose come:
$Var{"ClientName"} = "Pax Diablo";
(credo che la sintassi è giusto, non ho fatto qualsiasi sviluppo Perl per un po '). Il risultato finale è stato un sito web completo con un sacco di clienti, un sacco di memoriali, pagine di ricerca e un bel po 'di soldi mentre è durato (sono stato buttato fuori dal mercato dai direttori di pompe funebri fornendo la stessa cosa di un servizio "gratuito" all'interno i loro pacchetti regolari).
Ma il tutto è stato praticamente scritto in Perl minima cui solo fatto due cose:
- trasformato le variabili in istruzioni di assegnamento Perl; e
- ha eseguito il codice Perl specifico del mercato.
Sia l'esecuzione delle istruzioni di assegnazione sia il codice Perl specifico del mercato sono state eseguite con eval.
Quindi non è così inutile come si potrebbe pensare. Era un modo economico per introdurre lo scripting in un'applicazione.
Davvero, davvero non penso che la configurazione di caricamento sia molto buona per eval –
Questa è una questione di opinione. La configurazione consentita dall'utente era le variabili strettamente controllate che sono state accuratamente controllate per gli attacchi di iniezione. La parte non controllata era il codice specifico del mercato che comunque era stato scritto dallo sviluppatore, quindi non c'era pericolo. Tutto sommato, ha funzionato abbastanza bene. Ora non permetterei a un utente di digitare istruzioni come "$ x = 7;" e li elabora selvaggiamente - penso che sia quello che stavi ottenendo. – paxdiablo
La valutazione delle stringhe è l'unico modo per creare un nuovo codice con le stringhe. Questo è raramente necessario, ma ci sono alcuni casi d'uso validi, ad esempio quando si convertono modelli in codice eseguibile. Oltre a questo, ci sono pochissimi usi validi per questo. eval "require $module_name"
è un idioma ben noto, ma l'utilizzo ad esempio di Module::Load è un'idea migliore di quella IMO.
Proprio come la spiegazione: eval "require $ module_name" è necessario invece di "eval {require $ module_name}" perché "require EXPR" prova a richiedere un file mentre "require BAREWORD" (iE la sting valutata in questo eval) richiede un modulo . – willert
eval EXPR
può essere utilizzato per meta-programmazione nel caso in cui non si può fare affidamento su Moose o simili quadri per creare le classi al volo. Dai un'occhiata alla fonte di Exception::Class per vedere l'orrore pieno di questa tecnica.
Addendum: (@friedo)
Una caratteristica che fornisce oltre eval
simbolo tavolo manipolazione è la capacità di utilizzare Super e farlo funzionare come previsto:
package Foo;
sub msg { return 'Foo' }
package MyCodeGenerator;
use strict;
use warnings;
eval <<'EOPERL'; # '' -> no variable interpolation
package FooBar;
@FooBar::ISA = qw/Foo/;
sub msg {
my $self = shift;
return $self->SUPER::msg() . 'Bar'; # calls &Foo::msg
}
EOPERL
Anche se questo sarà (si spera) morire durante run-time, oppure è impostato per un lungo ore sessione di debug :
package BROKEN_Generator;
@FooBar::ISA = qw/Foo/;
*{'FooBar::msg'} = sub {
my $self = shift;
return $self->SUPER::msg() . 'Bar'; # tries to call &BROKEN_Generator::msg
}
facilmente in il mio Top 5 of things I hate about Perl!
Di solito non è necessario usare 'eval' per creare classi dinamicamente; puoi solo perdere tempo con il tavolo dei simboli. Sono stato sinceramente sorpreso di vedere quei 'eval's in Exception :: Class, però. Mi chiedo se siano veramente necessari tutti ... – friedo
Le dichiarazioni eval sono necessarie perché Exception :: Class si basa sulle chiamate SUPER in una gerarchia di classi creata dinamicamente. SUPER è legato al @ISA del pacchetto corrente, quindi non è possibile chiamarlo da sottotitoli anonimi e la manipolazione di tabelle di simboli naive si riduce. Si potrebbe aggirare questo problema, ma non è affatto facile e IIRC non prevedeva alternative preconfezionate nel 2000 quando E :: C era stato avviato. – willert
C'è NEXT (search.cpan.org/perldoc?NEXT) per quello (anche se probabilmente non era intorno al 2000). –
String eval è l'unico modo per:
- eseguire nuovo codice in un pacchetto runtime deciso
- metti sovraccarico a un pacchetto in fase di esecuzione (almeno secondo overload.pm)
- esecuzione arbitraria stringhe di Perl
- compilare tipo di macro sostituzioni
String eval non deve essere utilizzato per:
- valutare riferimenti simbolici
- eseguire qualsiasi codice da parte dell'utente
- intercettare gli errori
- se c'è qualche altro modo per farlo
eval può essere utilizzato anche per creare Ad- protocolli di comunicazione ad hoc tra diversi sistemi o lingue diverse che hanno anche eval (a condizione che tutto sia sicuro, ovviamente. JSON può essere visto come un sottoinsieme più sicuro, ma limitato di questo metodo)
- 1. I casi in cui float == e! = Non sono opposti diretti
- 2. In quali casi è necessario staccare gli eventi?
- 3. Ci sono dei puntatori in javascript?
- 4. casi in cui è file di log elmah.mvc trova
- 5. In quali casi è necessario includere <cassert>?
- 6. Alcuni casi in cui document.documentURI è disponibile ma non document.URL
- 7. Ci sono dei limiti all'utilizzo di string.lstrip() in python?
- 8. Non ci sono elementi in TeamProject in sito dei report
- 9. Ci sono specialità all'interno dei campi incorporati
- 10. Quali sono le condizioni in cui si può usare un'istruzione 'when' in Perl 5?
- 11. Ci sono situazioni in cui i test unitari sono dannosi per il codice?
- 12. È necessario un semplice esempio di parallelismo in Perl 6
- 13. È necessario convertire Stringa^in char *
- 14. Quali spazi dei nomi simbolo ci sono in Haskell?
- 15. Esistono casi in cui NON viene chiamato il distruttore in PHP?
- 16. Ci sono dei buoni benchmark Clojure?
- 17. Ci sono dei buoni controlli Griglia Delphi gratuiti/economici?
- 18. Quali sono i casi in cui NON dovrei usare FragmentManager's executePendingTransactions() (all'interno del thread principale)?
- 19. In Perl, come posso chiamare un metodo di cui ho il nome in una stringa?
- 20. In Java, perché gli oggetti array sono? Ci sono dei motivi specifici?
- 21. Perché non ci sono ObservableQueues in JavaFX?
- 22. Ci sono circostanze in cui un algoritmo hash può essere garantito univoco?
- 23. Quanti impliciti ci sono in Scala?
- 24. Esistono casi in cui Application.Exit() non solleva l'evento FormClosing?
- 25. Divisione selettiva di una stringa in Perl
- 26. Motivo per cui Odoo è lento quando ci sono enormi dati all'interno del database
- 27. Ci sono motivi per cui l'idioma StringPiece/StringRef non è più popolare?
- 28. ThreadPool.QueueUserWorkItem dei casi d'uso
- 29. Quali sono le ragioni ID GCM non è disponibile in alcuni casi in Android
- 30. Che diamine è una stringa Perl comunque?
Perché questo è -1? –
Non è un duplicato, ci sono molti usi di eval specifici per Perl 5 mentre il thread di riferimento discute il concetto generale di valutazione del codice run-time – willert
@willert Grazie per aver segnalato il mio errore. Sono sicuro che abbiamo già discusso di questo argomento, ma ho difficoltà a trovarlo. –