2010-02-23 11 views
12

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?

+0

Perché questo è -1? –

+0

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

+0

@willert Grazie per aver segnalato il mio errore. Sono sicuro che abbiamo già discusso di questo argomento, ma ho difficoltà a trovarlo. –

risposta

0

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.

+2

Davvero, davvero non penso che la configurazione di caricamento sia molto buona per eval –

+0

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

5

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.

+4

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

4

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!

+0

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

+1

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

+1

C'è NEXT (search.cpan.org/perldoc?NEXT) per quello (anche se probabilmente non era intorno al 2000). –

6

String eval è l'unico modo per:

  1. eseguire nuovo codice in un pacchetto runtime deciso
  2. metti sovraccarico a un pacchetto in fase di esecuzione (almeno secondo overload.pm)
  3. esecuzione arbitraria stringhe di Perl
  4. compilare tipo di macro sostituzioni

String eval non deve essere utilizzato per:

  1. valutare riferimenti simbolici
  2. eseguire qualsiasi codice da parte dell'utente
  3. intercettare gli errori
  4. 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)

Problemi correlati