2012-01-10 18 views
6

Nella maggior parte dei linguaggi di programmazione, gli argomenti passati a una funzione vengono valutati prima della, la funzione li utilizza, ovvero vengono valutati in modo impaziente.Perché la maggior parte dei linguaggi di programmazione utilizza una valutazione entusiasta per gli argomenti passati a una funzione?

Per me, sembra molto più sensato valutare gli argomenti solo una volta che la funzione li utilizza, cioè pigramente. Questo ha più senso per me perché sembra che avrebbe un vantaggio in termini di prestazioni: perché valutare cose che non sono mai nemmeno necessarie?

Inoltre, si supponga di voler implementare una funzione if che accetta un valore booleano, e un oggetto da restituire se la booleana è vero, e un altro oggetto da restituire se la booleana è falsa:

object if(bool condition, object valueIfTrue, object valueIfFalse) { 
    if(condition) return valueIfTrue; 
    return valueIfFalse; 
} 

In un linguaggio che valuta con entusiasmo gli argomenti, entrambi gli oggetti vengono sempre valutati anche se la funzione avrà sempre bisogno solo di uno di essi, che, nella migliore delle ipotesi, incorre in un leggero overhead non necessario e, nel peggiore dei casi, provoca un loop infinito.

Detto questo, dal momento che la maggior parte dei linguaggi di programmazione utilizza una valutazione impaziente degli argomenti delle funzioni, presumo che debba esserci una ragione per cui di solito è fatta in questo modo. C'è un grande vantaggio di una valutazione entusiasta qui che sto trascurando, è solo perché è stato più facile implementare i linguaggi in quel modo, è solo tradizione, o cosa?

+0

Perché è facile compilare/interpretare il codice in quei linguaggi non pigri. –

risposta

5

ci sono un paio di ragioni che ho visto per la valutazione ansioso, che sono entrambi importanti:

  1. valutazione Desideroso significa che gli effetti collaterali avvengono immediatamente e sempre.Se si utilizza la valutazione lenta, non è possibile fare affidamento sugli effetti collaterali di qualcosa che hai fatto in precedenza per avere effetto.
  2. La valutazione pigra porta con sé una certa quantità di memoria gonfia. In genere, è necessario molto meno spazio per memorizzare il risultato di un calcolo rispetto a quello per memorizzare lo thunk che descrive il calcolo. Ciò può comportare l'uso di troppa memoria (ad esempio, il rapporto tempo/memoria) e, a volte più importante, un tempo più difficile per capire le caratteristiche della memoria del programma/dell'algoritmo.

La valutazione pigra può essere uno strumento potente, ma non senza i suoi costi. Linguaggi puramente funzionali tendono a evitare il problema n. 1 perché non hanno effetti collaterali (in generale), ma a volte sono ancora morsi dal problema n. Le lingue che consentono la valutazione ritardata (le macro LISP sono una forma di questo, sebbene non la stessa di una valutazione pigra) possono avere il meglio di entrambi i mondi, ma a costo di un maggiore sforzo da parte del programmatore.

3

Opzione 1 - caricare tutti arguements nei registri, la funzione di chiamata

Opzione 2 - caricare primo argomento, di valutare se è necessario, attendere gasdotto CPU per cancellare, ottenere argomento successivo, di valutare se è necessario .... quindi carica i parametri necessari nei registri, esegui la funzione con logica aggiuntiva per contrassegnare quali registri sono in uso.

Un 'se' sta già andando a causare una rapina prestazioni in ogni caso, mentre si attende per vedere quale percorso di codice si sta eseguendo (un po 'salvato dalla branch prediction)

3

Affinché valutazione pigra al lavoro ci deve essere codice e dati aggiuntivi da qualche parte per tenere traccia di se un'espressione è stata valutata. In alcuni casi questo sarebbe più costoso di una valutazione entusiasta. Determinare se un'espressione può trarre beneficio da una valutazione lenta può richiedere una conoscenza di altissimo livello di come funziona il programma; il compilatore e/o l'interprete certamente non avranno questo tipo di conoscenza.

Inoltre, se la funzione o l'espressione hanno effetti collaterali, la strategia di valutazione lenta potrebbe far sì che i programmi si comportino in modo non intuitivo e difficile da eseguire il debug. Questo naturalmente non è un problema nei linguaggi di programmazione funzionale in cui non ci sono effetti collaterali di progettazione. In effetti, la valutazione lenta è la strategia predefinita per la maggior parte, se non tutti, dei linguaggi di programmazione funzionale.

Ciò detto, non c'è nulla che ti impedisca di utilizzare entrambe le strategie in luoghi diversi. Non sarei sorpreso se un approccio ibrido viene utilizzato in programmi non banali.

2

Oltre alle eccellenti risposte già fornite, c'è un altro problema pratico con la valutazione pigra. Se si dispone di una catena di espressioni solo pigramente valutate quando l'ultimo viene "utilizzato", può diventare piuttosto difficile identificare i colli di bottiglia delle prestazioni.

+0

Puoi fare un esempio? Sto cercando di visualizzare il tipo di codice di cui stai parlando. –

+0

Bene, supponiamo di avere un argomento 'x' per una funzione che, una volta valutata, ottiene il valore di un'altra variabile' y' e questo tipo di catena torna indietro. Potrebbero esserci alcune valutazioni lente e che sono colli di bottiglia, ma le vedrai quando valuti 'x'. Questo può essere fuorviante e l'origine a volte difficile da rintracciare. –

0

Indietro nel periodo Cretaceo, c'erano un certo numero di lingue che lo facevano. SNOBOL, per esempio. ALGOL 68 aveva una capacità "call by name", che faceva qualcosa del genere. E C (così come i suoi numerosi derivati) lo fa in una situazione molto specifica, che descrive come "cortocircuitare" un'espressione booleana. In generale, è quasi sempre una fonte di maggiore confusione e bug rispetto al potere di abilitazione.

+0

Non penso che la chiamata di Algol per nome sia stata una valutazione pigra, penso che stia passando riferimenti invece che valori. –

+0

La chiamata ALGOL per nome era più di una sostituzione testuale e non era esplicitamente un riferimento, quindi penso che si qualifichi come valutazione pigra. Anche se ora ci penso, potrebbe essere stato ALGOL 60 a introdurlo, non ALGOL 68. –

+1

Ahh ... gli anni '60, il "[Periodo Cretaceo] (http://stackoverflow.com/questions/1463321/was -algol-ever-used-for-mainstream-programming) "quando eravamo giganti e camminavamo sulla luna ... :-) Algol60 ha chiamato per nome. Algol68 non ha una chiamata per nome, tuttavia 68 ha una chiamata per riferimento. E inoltre, ... la valutazione pigra può essere implementata in un programma dal codificatore usando "proceduring", c.f. [Valutazione del cortocircuito usando le procedure] (http://stackoverflow.com/questions/9462051/short-circuit-evaluation-using-procedures) – NevilleDNZ

Problemi correlati