Non c'è nulla di "non funzionale" su let a = 4
rispetto a let a () = 4
. In effetti, in molte formulazioni astratte delle teorie del tipo, quest'ultimo è veramente zucchero sintattico per let a = fun () -> 4
.
La differenza principale è quando vuoi che l'espressione venga valutata, come hai detto tu. Se alla fine a
verrà valutato comunque, non ha senso avvolgerlo in una funzione. OTOH se pensi che ci sia una buona possibilità che a
non possa essere valutato, e la valutazione è molto costosa (o può anche fallire se non è soddisfatta una precondizione), allora potrebbe essere utile mantenere come una funzione. Tuttavia, in quest'ultimo caso devi stare attento a non valutare la funzione più di una volta.
Tuttavia, non sono sicuro che l'uso pervasivo della pigrizia sia tutto ciò che è comune in un linguaggio rigoroso come F #.
Modifica per indirizzare la tua domanda nei commenti:
In molte specifiche matematiche formali di un linguaggio, il costrutto let
associa un'espressione a una singola variabile:
let VARIABLE = EXPRESSION in EXPR
Il motivo è perché questo è più semplice di un let
che associa funzioni arbitrarie come let f x = 2 * x
. Invece, quest'ultimo è trattato come zucchero sintattico per il più dettagliato let f = fun x -> 2 * x
.
Tuttavia, nessuno dei due è più "funzionale" (se questa parola ha anche un significato ben definito). La programmazione funzionale non significa che dovresti tentare di utilizzare le funzioni ovunque possibile. Piuttosto, si limita a mettere le funzioni sullo stesso piano con altri valori in modo da poter manipolare sia le funzioni che i valori con la stessa facilità.
Il costrutto let
in Haskell ha un aspetto superficiale come quello di F #, ma semanticamente è molto diverso perché è non-strict ("pigro") per impostazione predefinita. Ciò significa che let x = 4 in 2 * x
in Haskell viene tradotto in modo più appropriato in let x = lazy(4) in 2 * Lazy.force x
.
Il costrutto let
dovrebbe non essere confuso con assignments , che sono una cosa completamente diversa in quanto richiede una mutazione. Per contrasto, let non muta nulla: introduce semplicemente una nuova variabile. F # sfuma il limite perché consente di mescolare le funzioni pure e impure, quindi le associazioni let
possono avere effetti collaterali e quindi il modo in cui li si lega (come funzioni o valori) avrà importanza.
In un linguaggio puro, let
binding non può causare effetti collaterali, ma l'ordine di valutazione è ancora valido per due motivi:
- Efficienza: perché non abbiamo risorse infinite e pazienza infinita.
- Divergenza: le funzioni possono ancora fallire o entrare in un ciclo infinito.
Quindi, anche nelle lingue pure , è ancora importante sapere se la valutazione è fatta in modo avido o pigramente.