2009-06-25 15 views
5

Peter Norvig in PAIP dice:
"in lische moderni ... eval viene utilizzata meno spesso (in realtà, nello Schema non c'è eval a tutti)" "se vi trovate utilizzando eval, è probabilmente stanno facendo la cosa sbagliata ".EVAL in SCHEMA

Quali sono alcuni dei modi per aggirare l'utilizzo di eval in combinazione? Non vi sono casi in cui la valutazione è assolutamente necessaria?

risposta

7

Ci sono casi in cui è necessario eval, ma coinvolgono sempre programmi avanzati che fanno cose come caricare dinamicamente del codice (ad esempio, un servlet in un server web). Per quanto riguarda un modo per "aggirare" il suo utilizzo - che dipende dal problema reale che stai cercando di risolvere, non esiste una soluzione magica per evitare eval eccetto per ... eval.

(BTW, la mia ipotesi è che PAIP è stato scritto molto tempo fa, prima eval è stato aggiunto alla relazione Scheme.)

+0

Mi dispiace non potrei essere più specifico su ciò che volevo nella domanda. Ma ciò che è interessante è che ho sempre pensato che eval fosse sempre parte integrante di Scheme. Comunque spero di vedere più usi e "abusi" di eval in CS G111. :) – unj2

+1

Sì, 'eval' * è * una parte integrante di Scheme, ma è davvero necessaria solo nei casi avanzati. La regola generale è: se non si conoscono i motivi tecnici che richiedono l'uso di 'eval', allora * non * ne ha bisogno. (E questa è una risposta seria!) In ogni caso, sì, avrai un sacco di 'eval'ing in CSG111 se hai intenzione di prenderlo, e se tutto va bene se lo ricordi, chiedimi al riguardo. –

1

Innanzitutto, PAIP è scritto per Common Lisp, non Scheme, quindi non so che direbbe la stessa cosa. Le macro CL hanno più o meno lo stesso valore di eval, anche se al momento della compilazione invece del tempo di esecuzione e altre cose che potresti fare. Se mi mostrassi un esempio dell'uso di eval in Common Lisp, potrei provare a trovare altri metodi per fare la stessa cosa.

Non sono un programmatore Scheme. Posso solo parlare dal punto di vista di Norvig, come programmatore Common Lisp. Non penso che stesse parlando di Scheme, e non so se conoscesse o conoscesse bene Scheme.

Secondo, Norvig dice "probabilmente stai facendo la cosa sbagliata" piuttosto che "stai facendo la cosa sbagliata". Ciò implica che, per quanto ne sa, ci sono momenti in cui eval è la cosa giusta da usare. In una lingua come C, direi la stessa cosa su goto, anche se sono abbastanza utili in alcune circostanze limitate, ma la maggior parte dell'uso di goto è di persone che non conoscono meglio.

+0

"Non so se conosce Scheme particolarmente bene". Questa affermazione è abbastanza incredibile. "ci sono volte in cui l'eval è la cosa giusta da usare". Questa era la mia seconda domanda. Come praticanti programmatori, hai usato eval? – unj2

+1

Ovviamente, Norvig è estremamente bravo a Common Lisp, avendo scritto un libro davvero eccellente. Questo non si applica al regime. Stroustrup sarebbe necessariamente una buona autorità sul modo migliore di fare qualcosa in Java o Objective-C? Quella famiglia di lingue non è più disparata della famiglia Lisp, compresi Common Lisp e Scheme. –

+0

hmmm lui implementa lo schema in lisp..oh beh non lo so. ma suppongo che si trovi nello spettro "sa particolarmente bene". – unj2

-1

È possibile scrivere un interprete di schema nello schema. Questo è certamente possibile, ma non è pratico.

Concesso, questa è una risposta generale, poiché non ho uno schema utilizzato, ma potrebbe comunque esservi d'aiuto. :)

+0

Non è qui vicino la risposta che volevo. :) – unj2

4

Si sbaglia. Naturalmente c'è lo eval in Scheme.

+0

Quale schema? Non credo che r4rs abbia richiesto che Eval fosse presente. – Aaron

+3

R5RS http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.5 – newacct

+3

@newacct PAIP è arrivato nel 1992 e l'R4RS non ha avuto valutazione. R5Rs è arrivato nel 1998 e ha aggiunto eval, dynamic-wind e valori :) – Sylwester

0

Un uso che ho visto per 'eval' in ambienti di scripting è quello di parametrizzare alcuni codice con valori di runtime. per esempio, in psuedo-C:

param = read_integer(); 
fn = eval("int lambda(int x) { 
      int param = " + to_string(param) + "; 
      return param*x; }"); 

Spero che tu lo trovi davvero brutto. Incollare le stringhe per creare codice in fase di runtime? Ick. In Scheme e in altri Lisps con ambito lessicale, è possibile eseguire funzioni parametrizzate senza utilizzare eval.

(define make-my-fn 
    (lambda (param) 
    (lambda (x) (* param x))) 

(let* ([ param (read-integer) ] 
     [ fn  (make-my-fn param ]) 
    ;; etc. 
) 

Come è stato menzionato, codice caricamento dinamico e tale ancora bisogno eval, ma il codice parametrizzata e codice composizione può essere prodotto con funzioni di prima classe.

3

Avrete bisogno di eval in un caso molto raro. Il caso che viene in mente prima è quando costruirai un programma con un programma e poi lo eseguirai. Questo succede principalmente con l'algoritmo genetico per esempio. In questo caso costruisci molti programmi randomizzati che dovrai eseguire.Avere eval in congiunzione con il codice essendo i dati rendono il linguaggio di programmazione più semplice per fare algoritmo genetico.

Avere queste proprietà ha un costo elevato (in termini di velocità e dimensioni del programma) perché rimuoverete tutte le possibilità di eseguire l'ottimizzazione del tempo di compilazione sul codice che verrà valutato e sarà necessario mantenere l'intero interprete in il tuo binario risultante.

Di conseguenza è considerato un design scadente utilizzare eval quando può essere evitato.

3

L'affermazione che Schema non ha eval è inaccurata almeno per le versioni più recenti dello standard Scheme (R5RS e versioni successive). Di solito, quello che vuoi è una macro, che genererà il codice in fase di compilazione.

È vero che eval deve essere evitato. Per cominciare, non ho mai visto una definizione soddisfacente di come dovrebbe comportarsi, ad esempio:

  1. Quali espressioni di ambiente devono essere valutate in assenza di ambiente?
  2. Quando passi in un ambiente, come funzionano? Ad esempio, gli standard non specificano il modo in cui è possibile pre-associare un valore in quell'oggetto ambiente.

Detto questo, ho lavorato con un'applicazione schema che utilizza eval per generare il codice in modo dinamico in fase di esecuzione per i casi in cui la struttura del calcolo non può essere noto al momento della compilazione. L'intento è stato quello di ottenere che il sistema Schema a compili il codice in fase di esecuzione per motivi di prestazioni, e la difficoltà è che non esiste un modo standard per comunicare a un sistema Scheme "compilare questo codice".

Va da sé che anche lo eval può rappresentare un enorme rischio per la sicurezza. Non dovresti mai eval qualcosa che non ha un enorme muro di separazione dall'input dell'utente. In sostanza, se si desidera utilizzare eval in modo sicuro, si dovrebbe farlo nel contesto della fase di generazione del codice di un sistema simile a un compilatore, dopo aver analizzato alcuni input (utilizzando una grammatica ampiamente definita!).