Perché la valutazione non viene utilizzata ovunque?

29

Ho appena appreso come funziona la valutazione pigra e mi stavo chiedendo: perché la valutazione non pigra è applicata a tutti i software attualmente prodotti? Perché usare ancora la valutazione entusiasta?

    
posta John Smith 11.12.2011 - 19:18
fonte

6 risposte

37

La valutazione pigra richiede un sovraccarico contabile, devi sapere se è stato ancora valutato e cose del genere. La valutazione stimolante viene sempre valutata, quindi non devi saperlo. Questo è particolarmente vero nei contesti simultanei.

In secondo luogo, è banale convertire la valutazione appassionata in una valutazione lazy inserendola in un oggetto funzione da chiamare successivamente, se lo si desidera.

In terzo luogo, la valutazione pigra implica una perdita di controllo. Cosa succede se ho pigramente valutato la lettura di un file da un disco? O ottenere il tempo? Non è accettabile.

La valutazione stimolante può essere più efficiente e più controllabile e viene banalmente convertita in valutazione lenta. Perché vorresti una valutazione pigra?

    
risposta data 11.12.2011 - 19:32
fonte
16

Soprattutto perché il codice e lo stato pigri possono mescolare male e causare alcuni bug difficili da trovare. Se lo stato di un oggetto dipendente cambia il valore del tuo oggetto pigro può essere sbagliato quando viene valutato. È molto meglio che il programmatore codifichi esplicitamente l'oggetto in modo che sia pigro quando sa che la situazione è appropriata.

Nota a margine Haskell utilizza la valutazione Lazy per tutto. Questo è possibile perché è un linguaggio funzionale e non utilizza lo stato (tranne in alcune circostanze eccezionali in cui sono chiaramente contrassegnati)

    
risposta data 11.12.2011 - 20:00
fonte
13

La valutazione pigra non è sempre migliore.

I vantaggi in termini di prestazioni della valutazione lazy possono essere grandi, ma non è difficile evitare la maggior parte della valutazione non necessaria in ambienti desiderosi, sicuramente pigri per renderli semplici e completi, ma raramente è una valutazione non necessaria nel codice un problema grave.

La cosa buona della valutazione lazy è quando ti permette di scrivere codice più chiaro; ottenere il decimo primo filtrando una lista infinita di numeri naturali e prendendo il decimo elemento di quella lista è uno dei modi più concisi e chiari di procedere: (pseudocodice)

let numbers = [1,2...]
fun is_prime x = none (map (y-> x mod y == 0) [2..x-1])
let primes = filter is_prime numbers
let tenth_prime = first (take primes 10)

Credo che sarebbe abbastanza difficile esprimere le cose in modo conciso senza pigrizia.

Ma la pigrizia non è la risposta a tutto. Per i principianti, la pigrizia non può essere applicata in modo trasparente in presenza di stato, e credo che lo stato non possa essere rilevato automaticamente (a meno che non si stia lavorando, ad esempio, in Haskell, quando lo stato è abbastanza esplicito). Quindi, nella maggior parte dei linguaggi, la pigrizia deve essere eseguita manualmente, il che rende le cose meno chiare e quindi rimuove uno dei grandi vantaggi della eval lazy.

Inoltre, la pigrizia ha degli svantaggi in termini di prestazioni, poiché comporta un sovraccarico significativo nel mantenere le espressioni non valutate in giro; usano lo spazio di archiviazione e sono più lenti a lavorare rispetto ai valori semplici. Non è raro scoprire che devi codice bisognoso perché la versione lenta è lenta come un cane, ea volte è difficile ragionare sulle prestazioni.

Dato che tende a succedere, non esiste una strategia migliore in assoluto. Lazy è fantastico se puoi scrivere codice migliore sfruttando strutture di dati infiniti o altre strategie che ti consentono di utilizzarle, ma desiderare può essere più facile da ottimizzare.

    
risposta data 11.12.2011 - 20:11
fonte
3

Ecco un breve confronto tra vantaggi e svantaggi della valutazione avida e pigra:

  • Valutazione stimolante:

    • Potenziale sovraccarico di valutazione inutile di roba.

    • Valutazione rapida e senza impedimenti.

  • Valutazione pigra:

    • Nessuna valutazione non necessaria.

    • Spese generali di contabilità ad ogni utilizzo di un valore.

Quindi, se hai molte espressioni che non devono mai essere valutate, pigro è meglio; eppure se non hai mai un'espressione che non ha bisogno di essere valutata, pigro è puro overhead.

Ora, diamo un'occhiata al software del mondo reale: quante delle funzioni che scrivi non richiedono la valutazione di tutti i loro argomenti? Soprattutto con le funzioni brevi moderne che fanno solo una cosa, la percentuale di funzioni rientra in questa categoria è molto bassa. Pertanto, la valutazione lazy introdurrebbe il sovraccarico contabile per la maggior parte del tempo, senza la possibilità di salvare effettivamente qualcosa.

Di conseguenza, la valutazione pigra semplicemente non paga in media, la valutazione entusiasta è la soluzione migliore per il codice moderno.

    
risposta data 07.06.2015 - 09:25
fonte
3

Come notato da @DeadMG, la valutazione Lazy richiede un sovraccarico contabile. Questo può essere costoso rispetto alla valutazione entusiasta. Considera questa affermazione:

i = (243 * 414 + 6562 / 435.0 ) ^ 0.5 ** 3

Questo richiederà un po 'di calcolo per calcolare. Se uso la valutazione lazy, allora ho bisogno di controllare se è stato valutato ogni volta che lo uso. Se questo è all'interno di un anello stretto pesantemente utilizzato, il sovraccarico aumenta in modo significativo, ma non vi è alcun vantaggio.

Con una valutazione entusiasta e un compilatore decente la formula viene calcolata in fase di compilazione. La maggior parte degli ottimizzatori sposta il compito da qualsiasi loop in cui si verifica, se appropriato.

La valutazione pigra è più adatta al caricamento di dati a cui si accede di rado e con un elevato sovraccarico da recuperare. È quindi più appropriato per i casi limite rispetto alla funzionalità di base.

In generale, è buona norma valutare le cose a cui si accede frequentemente il prima possibile. La valutazione pigra non funziona con questa pratica. Se si accederà sempre a qualcosa, tutta la valutazione pigra andrà a sommarsi. Il costo / beneficio dell'utilizzo della valutazione lazy diminuisce man mano che l'accesso all'elemento diventa meno probabile.

Utilizzare sempre la valutazione lazy implica anche l'ottimizzazione iniziale. Questa è una cattiva pratica che spesso si traduce in un codice molto più complesso e costoso che potrebbe altrimenti essere il caso. Sfortunatamente, l'ottimizzazione prematura spesso porta a un codice che si comporta più lentamente di un codice più semplice. Finché non puoi misurare l'effetto dell'ottimizzazione, è una cattiva idea ottimizzare il tuo codice.

Evitare l'ottimizzazione prematura non è in conflitto con le buone pratiche di codifica. Se le buone pratiche non sono state applicate, le ottimizzazioni iniziali possono consistere nell'applicare buone pratiche di codifica come lo spostamento di calcoli da loop.

    
risposta data 11.12.2011 - 20:04
fonte
3

Se potenzialmente è necessario valutare appieno un'espressione per determinarne il valore, la valutazione lenta può essere uno svantaggio. Supponiamo di avere una lunga lista di valori booleani e vogliamo scoprire se tutti di essi sono veri:

[True, True, True, ... False]

Per fare questo dobbiamo guardare l'elemento ogni nell'elenco, indipendentemente da cosa, quindi non c'è possibilità di pigramente di tagliare la valutazione. Possiamo usare una piega per determinare se tutti i valori booleani nella lista sono veri. Se usiamo una piega a destra, che utilizza la valutazione lazy, non otteniamo nessuno dei benefici della valutazione lazy perché dobbiamo esaminare ogni elemento della lista:

foldr (&&) True [True, True, True, ... False] 
> 0.27 secs

In questo caso, una piega a destra sarà molto più lenta di una rigida piega a sinistra, che non utilizza una valutazione lenta:

foldl' (&&) True [True, True, True, ... False] 
> 0.09 secs

Il motivo è che una rigida piega a sinistra utilizza la ricorsione in coda, il che significa che accumula il valore di ritorno e non si accumula e memorizza in una grande catena di operazioni. Questo è molto più veloce del lazy fold giusto perché entrambe le funzioni devono guardare comunque l'intera lista e la piega destra non può usare la ricorsione della coda. Quindi, il punto è, dovresti usare tutto ciò che è meglio per il compito a portata di mano.

    
risposta data 07.06.2015 - 08:59
fonte

Leggi altre domande sui tag