Se dico let 5 = 10
, perché 5 + 1
restituisce 6
anziché 11
?Informazioni su "let 5 = 10`
risposta
Quando si dice
let 5 = 10
non è una ridefinizione del 5, è un pattern matching, la stessa che si verifica quando si dice
foo 5 = undefined
... foo 10 ...
Il modello non è sufficiente se è sempre abbinato.
Nelle let-espressioni la corrispondenza è pigra. Ciò significa che la corrispondenza viene eseguita solo quando viene valutata una variabile vincolata da essa. Questo ci permette di scrivere cose come
let foo = undefined in 10
Nella tua espressione, nessuna variabile è vincolata, quindi il modello non è mai abbinato.
Probabilmente tali modelli senza variabili non hanno senso nei legami e dovrebbero essere rilevati dal compilatore, ma il linguaggio non li vieta.
Rassicurato 'let (5, x) = (10, True) in x' consegna' *** Eccezione:
Questo è sciocco per legami letali, ma non per tutti: ad es. 'only5 xs = [5 | 5 <- xs] 'ha senso (se stai bene con liste' fail'). – user3237465
@ user3237465 sì, intendevo solo let-binding. In aggiornamento. –
Fondamentalmente,
let 5 = 10 in ...
è equivalente a
case 10 of ~5 -> ...
nota la ~
, che segna un pigro, o irrefutabile modello. Questo è un modello che corrisponde a tutto e che rimanda la corrispondenza al punto in cui è effettivamente richiesta una variabile. Non ci sono variabili nel modello 5
, quindi non succede mai niente.
Questo caso d'angolo è abbastanza inutile, e probabilmente il compilatore dovrebbe emettere un avvertimento qui.
Per chiarire il significato di modelli pigri, considerare questo:
case f 3 of
(x,y) -> g 10 x y
qui f 3
viene valutata per prima (a WHNF), esponendo il costruttore coppia. Quindi x,y
sono associati ai componenti della coppia (non ancora valutata). Infine, viene calcolato g 10
, il risultato viene applicato a x
(che potrebbe essere richiesto ora), quindi a (che potrebbe richiedere x
o).
In confronto,
case f 3 of
~(x,y) -> g 10 x y
non inizia a valutare f 3
. Invece x
è legato al valore non valorizzato fst (f 3)
e è legato al valore non valutato snd (f 3)
. Iniziamo invece con la valutazione di g 10
. Quindi, lo applichiamo a x
: ciò potrebbe causare la richiesta di x
, innescando la valutazione di f 3
. Quindi, applichiamo il risultato a , causando una valutazione simile.La maggior parte dell'implementazione sarà in realtà condivide il risultato di f 3
tra x
e in modo che venga calcolato al massimo una volta.
Come @ n. sta dicendo, tu sei il modello di corrispondenza. Ecco alcuni esempi.
modello corrisponde può avere successo
Prelude> let (a, 10) = (15, 10) in a
15
o fallire.
Prelude> let (a, 10) = (15, 15) in a
*** Exception: <interactive>:5:5-22: Irrefutable pattern failed for pattern (a, 10)
Poiché Haskell è pigro, il codice verrà eseguito correttamente se non si utilizza il valore risultante. Questo è in sostanza quello che stai facendo:
Prelude> let (a, 10) = (15, 15) in "Something else"
"Something else"
Nota che i tipi devono ancora verificare:
Prelude> let (a, 10, 999) = (15, 15) in "Something else"
<interactive>:7:20: error:
• Couldn't match expected type ‘(t, Integer, Integer)’
with actual type ‘(Integer, Integer)’
• In the expression: (15, 15)
In a pattern binding: (a, 10, 999) = (15, 15)
In the expression: let (a, 10, 999) = (15, 15) in "Something else"
• Relevant bindings include a :: t (bound at <interactive>:7:6)
" Poiché Haskell è pigro, il tuo codice andrà a buon fine se non usi il valore risultante "- Vale la pena ricordare che importa anche che' let' le associazioni corrispondono pigramente per impostazione predefinita. 'case (15, 15) di {(a, 10) ->" Qualcos'altro "}' si blocca, mentre 'case (15, 15) di {~ (a, 10) ->" Qualcos'altro "}' (che , grazie alla corrispondenza pigra, [equivale al tuo terzo esempio] (https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-440003.12)) ha successo. – duplode
@duplode, penso che lazy default in 'let' e' where' sia stata una cattiva idea, ed è la ragione per cui i pattern bang possono essere confusi a volte. – dfeuer
@dfeuer Che dire del binding a una lista infinita? Per esempio 'let nats = [1 ..] in takeWhile isOkay nats' – Teodor
- 1. let vs var performance
- 2. Let & sintassi mut
- 3. Informazioni su timedelta
- 4. Realm su Windows 10
- 5. Informazioni su Linux Scheduler
- 6. Informazioni su JavaScript Truthy and Falsy
- 7. Informazioni su os.fork e Queue.Queue
- 8. Utilizzando guardie let .. in espressioni
- 9. Prestazioni lente glTexSubImage2D su Nexus 10/Android 4.2.2 (Samsung Exynos 5 con Mali-T604)
- 10. Salva flusso RTSP continuo su file mp4 lunghi 5-10 minuti
- 11. informazioni su L-Systems
- 12. Informazioni su IronJS
- 13. Informazioni su UIGraphicsGetCurrentContext()
- 14. Informazioni su convertPoint: toView:
- 15. informazioni su javascript document.createElement()
- 16. Informazioni su boundCenterBottom()
- 17. Ulteriori informazioni su Parsing
- 18. Informazioni su Gradle's mavenDeployer
- 19. Informazioni su TodoMVC Esempio
- 20. Informazioni su SFINAE
- 21. Informazioni su JVM Better
- 22. Informazioni su Big O
- 23. Informazioni su Node.JS async.parallel
- 24. Informazioni su std :: forward
- 25. Informazioni su ESB
- 26. Informazioni su TreeMaps
- 27. Informazioni su Deferred.pipe()
- 28. Informazioni su Traceview
- 29. Informazioni su RenderScript
- 30. Informazioni su JavaScript originalEvent
Una risposta immediata sarebbe "perché non si può ridefinire ciò che' 5' è". Tuttavia, in realtà sono abbastanza sorpreso scrivendo che "Let 5 = 10' sia persino possibile! – duplode
quello che puoi fare è 'overload' il' + ':' let 1 + 1 = 3 in 1 + 1';) – Carsten
btw: Penso che il '5' in' let 5 = 10' sia ancora un pattern (solo uno che non è mai abbinato) quindi non legherà nulla (come in 'let (x, 5) = (6,6)') – Carsten