indietro

  • eval ESPR
  • eval BLOCCO
  • eval

    Nella prima forma, il valore restituito da ESPR viene analizzato sintatticamente ed eseguito come se fosse un piccolo programma Perl. Il valore dell'espressione (che viene di per sé determinato all'interno del contesto scalare) viene prima controllato dal punto di vista sintattico e, se non ci sono stati errori, eseguito nel contesto lessicale del programma Perl corrente, in maniera che tutte le definizioni di formato, le subroutine, e i valori dati alle variabili rimangano intatti. Va notato che il valore viene verificato sintatticamente ogni qualvolta l'eval effettua un'esecuzione. Se ESPR viene omessa, esso valuta $_. Questa forma viene usata tipicamente per ritardare la verifica sintattica e la successiva esecuzione del testo di ESPR fino al tempo di esecuzione.

    Nella seconda forma, il codice all'interno del BLOCCO viene verificato sintatticamente solo una volta, allo stesso momento in cui il codice che circonda lo stesso eval viene verificato sintatticamente, ed eseguito all'interno del contesto del programma Perl corrente. Questa forma viene usata tipicamente per catturare le eccezioni in maniera più efficiente che non la prima (vedete qui sotto), pur fornendo anche il vantaggio di controllare il codice dentro BLOCCO a tempo di compilazione.

    Il punto e virgola finale, se presente, potrebbe essere omesso dal valore di ESPR o all'interno del BLOCCO.

    In entrambe le forme, il valore restituito è il valore dell'ultima espressione valutata all'interno del mini-programma; può anche essere usata un'istruzione return, proprio come per le subroutine. L'espressione che fornisce il valore restituito, viene valutata in un contesto vuoto, scalare oppure di lista, a seconda del contesto dell'eval stesso. Si veda wantarray per maggiori informazioni su come può essere valutata la valutazione del contesto.

    Se ci fosse un errore di sintassi o un errore a tempo di esecuzione oppure se venisse eseguita un'istruzione die, eval restituisce un valore indefinito e in $@ viene posto il messaggio d'errore. Se non ci fossero errori, $@ viene garantito essere una stringa nulla. Fate attenzione al fatto che utilizzare eval non impedisce al perl di stampare gli avvertimenti su STDERR, né tantomeno il testo degli avvertimenti viene memorizzato in $@. Per fare entrambe le cose, dovete usare l'agevolazione data da $SIG{__WARN__} oppure disabilitare gli avvertimenti all'interno del BLOCCO o ESPR utilizzando no warnings 'all'. Consultate warn, perlvar, warnings e perllexwarn.

    Va notato che, dato che eval cattura gli errori altrimenti blocanti, è utile per determinare se una particolare caratteristica (quale socket o symlink) è implementata. È anche il meccanismo di cattura delle eccezioni, dove l'operatore die viene usato per sollevare le eccezioni.

    Se il codice che deve essere eseguito non varia, potete usare la forma eval-BLOCCO per catturare gli errori a tempo di esecuzione senza incorrere nella penalizzazione di ricompilare ogni volta. L'errore, se c'è, viene ancora restituito in $@. Esempi:

        # rende la divisione per zero non bloccante
        eval { $risposta = $a / $b; }; warn $@ if $@;
        # stessa cosa, ma meno efficiente
        eval '$risposta = $a / $b'; warn $@ if $@;
        # un errore a tempo di compilazione
        eval { $risposta = };		# ERRATO
        # un errore a tempo di esecuzione
        eval '$risposta =';	# imposta $@

    Usare la forma eval{} per catturare le eccezioni nelle librerie, presenta qualche complicanza. A causa del corrente, opinabilmente non corretto, stato degli hook di __DIE__, potreste non voler innescare alcun hook per quei __DIE__ che il codice utente potrebbe aver installato. Per questo scopo si può utilizzare il costrutto local $SIG{__DIE__}, come mostrato in questo esempio:

        # una trappola molto privata per l'eccezione divisione-per-zero
        eval { local $SIG{'__DIE__'}; $risposta = $a / $b; };
        warn $@ if $@;

    Questo ha un significato speciale, dato che gli hook di __DIE__ possono chiamare die un'altra volta, e ciò ha l'effetto di cambiare i loro messaggi d'errore:

        # gli hook di __DIE__ pssono modificare i messaggi d'errore
        {
           local $SIG{'__DIE__'} =
                  sub { (my $x = $_[0]) =~ s/pippo/pluto/g; die $x };
           eval { die "pippo qua e` vivo" };
           print $@ if $@;                # stampa "pluto qua e` vivo"
        }

    Visto che questo favorisce le azioni a distanza, questo comportamento non intuitivo sarà probabilmente risolto in una versione ventura.

    Con un eval, dovreste prestare particolare attenzione nel ricordare cosa si sta esaminando quando:

        eval $x;		# CASO 1
        eval "$x";		# CASO 2
        eval '$x';		# CASO 3
        eval { $x };	# CASO 4
        eval "\$$x++";	# CASO 5
        $$x++;		# CASO 6

    I casi 1 e 2 qua sopra, hanno un comportamento identico: essi eseguono il codice contenuto nella variabile $x. (Sebbene il caso 2 ha delle virgolette che sono ingannevoli che fanno sì che il lettore si chieda cos'altro stia accadendno (nulla)). I casi 3 e 4, similmente, si comportano allo stesso modo: eseguono il codice in '$x', che non fa altro che restituire il valore di $x. (Il caso 4 è preferibile solamente per ragioni visuali, ma ha anche il vantaggio di compilare a tempo di compilazione invece che a tempo di esecuzione). Il caso 5 è un luogo dove, di norma, vorreste usare le virgolette, eccetto che in questa particolare situazione, invece potete semplicemente usare i riferimenti simbolici, proprio come nel caso 6.

    eval BLOCCO non viene considerata come un ciclo, dunque le istruzioni di controllo di un ciclo next, last o redo non possono essere usate per lasciare o reiniziare il blocco.

    Va notato che come caso davvero speciale, un eval '' eseguito all'interno del package DB non vede l'usuale scope lessicale che lo circonda ma piuttosto lo scope del primo pezzo di codice che non appartiene al package DB che l'ha chiamato. Di norma, non si ha bisogno di preoccuparsi di questo a meno che non si stia scrivendo un debugger del Perl.