== PROGRAMMAZIONE AD ATTORI == 1. Definizione di paradigma ad attori 2. Differenze fra il paradigma ad attori e quello ad agenti 3. Punti di forza e di debolezza del paradigma ad attori == ERLANG == 4. Erlang: genesi, storia, obiettivi, punti di forza == PROGRAMMAZIONE FUNZIONALE == 5. Definizione di paradigma funzionale 6. Punti di forza e di debolezza del paradigma funzionale 7. Definizione di funzioni higher-order 8. Definizione di oggetti di prima classe 9. Immutabilità: vantaggi e svantaggi 10. Strictness vs lazyness 11. La rappresentazione dei dati nei linguaggi funzionali 12. La garbage collection nei linguaggi funzionali 13. Pattern, pattern matching e guardie == ERLANG == 14. Hot-swap del codice in Erlang: come invocarlo e come è implementato == GARBAGE COLLECTION == 15. Definizione di garbage collection 16. Vantaggi e svantaggi della garbage collection 17. La tecnica del reference counting per l'implementazione di garbage collection 18. Algoritmi mark&sweep per la garbage collection 19. Garbage collection generazionale 20. Gestione dei puntatori dallo heap young allo heap old 21. Gestione dei puntatori dallo heap old allo heap young quando necessaria (e sapere quando lo è) = PROGRAMMAZIONE FUNZIONALE == 22. Chiamate di funzione di coda, funzioni tail ricorsive e relativa ottimizzazione 23. Costrutti tipici dei linguaggi di programmazione funzionale in sintassi Erlang e loro uso: pattern matching, case analysis, local function declaration (sia nella versione ricorsiva che in quella non ricorsiva), list comprehension 24. Record vs tuple: differenze (o loro mancanza) a run-time, vantaggi e svantaggi, implementazione di record tramite macro 25. Macro igieniche vs non-igieniche: il problema della cattura dei nomi 26. Esempi di comandi implementabili tramite macro ma non tramite funzioni in un linguaggio di programmazione eager (call-by-value). Possibili workaround cambiando la sintassi e passando funzioni invece di espressioni. 27. Le eccezioni: il costrutto try .. of .. catch .. after. Attenzione alla semantica: cosa accade se un'eccezione viene sollevata nel try? Se viene sollevata in un ramo dopo l'of? In un ramo dentro al catch? Nell'after? Se viene sollevata sia nel catch che nel try? Etc. 28. Come vengono implementate le eccezioni? Come interferiscono con la tail-call optimization? = ERLANG = 39. Costrutti per la programmazione concorrente: send asincrona, receive asincrona, spawning di un nuovo processo, link/unlink, monitor/demonitor e intercettamento degli EXIT message per processi linked/monitored 40. Registrazione/pubblicazione del PID su un singolo nodo e in ambiente distribuito 41. Mobilità del codice: in quali situazioni migrare il codice verso un altro nodo è consigliabile? Come si può implementare in Erlang la migrazione del codice? 42. Come stabilire una connessione fra più nodi Erlang e come registrare PID in modo da contattare attori in esecuzione su altri nodi. 43. Il modello di sicurezza di Erlang basato su token (e perchè per lanciare due nodi su una stessa macchina non è necessario specificare alcun token) 44. Comunicazione con librerie e processi esterni: il meccanismo basato su porte. 45. Context switch, cooperative multi-tasking, preemptive multi-tasking 46. Implementazione del preemptive multi-tasking in Erlang senza far ricorso a interrupt hardware 47. Implementazione di Erlang: strutture dati usate a run-time per rappresentare il set di processi in esecuzione e la loro memoria. 48. Erlang Term Storage (ETS) = FUTURES = 49. Definizione di future/promise e possibili semantiche operazionali. Thunks. 50. Implementazione di future in Erlang 51. Implementazione di thunks in OCaml 52. Varianti sintattiche sui future: future+promise, futures alla JavaScript, etc. 53. Future pipelining, ovvero come i future riducono automaticamente la latency per mezzo di comunicazioni locali ai nodi nel caso il future che fa una yield sia sullo stesso nodo del future al quale viene fatta la yield = CHIUSURE = 54. Definizione di chiusura; differenze sintattiche fra funzioni e chiusure 55. Modello di esecuzione di C (puntatori a funzioni, niente funzioni annidate) e di Pascal (funzioni annidate, niente puntatori a funzioni) 56. Problematiche relative all'implementazione di chiusure 56. Come implementare una chiusura a basso livello (p.e. in C) 57. Funzioni anonime 58. Vantaggi dell'avere chiusure: chiusure per controllare l'accesso (data e function hiding); chiusure per decorare funzioni; chiusure per avere stato locale protetto; chiusure per implementazioni di operatori di controllo; etc. = OCaml = 59. Cenni storici all'evoluzione dei linguaggi della famiglia ML 60. Il core funzionale di ML: funzioni, definizioni globali e locali, costruttori, pattern matching, eccezioni 61. Abbreviazioni di tipo in OCaml e confronto strutturale di tipo 62. Algebraic Data Types in OCaml: dichiarazione, pattern matching, check di esaustività e non sovrapposizione, = ALGEBRAIC DATA TYPES = 63. Implementazione di ADT in C 64. Implementazione di ADT in Erlang (compresa la rappresentazione in memoria) 65. Implementazione di ADT in class based languages, usando il tipo dell'oggetto come tag 66. Sealing: concetto, codifica in Java, uso per implementare ADT 67. Implementazione di ADT in Kotlin 68. Tipi nullable in Kotlin e relativi cast automatici 69. Il tipo option/maybe per la rappresentazione di valori opzionali: confronto con i tipi nullable in Kotlin. = POLYMORPHIC VARIANTS E L'ESPRESSION PROBLEM = 70. Definizione dell'espression problem e associate problematiche 71. La soluzione all'espression problem in linguaggi object-oriented e relative problematiche 72. Open recursion vs closed recursion 73. Polymorphic variants in OCaml: sintassi, cenni al relativo tipaggio e loro rappresentazione a run-time 74. La soluzione dell'espression problem in OCaml combinando open recursion + polymorphic variants = GENERALIZED ABSTRACT DATA TYPES = 75. Sintassi dei Generalized Abstract Data Types e loro rappresentazione a run-time 76. Applicazioni dei GADT: imposizione di invarianti alle strutture dati e relative semplificazioni del codice; ad-hoc polymorphism (e.g. implementazione di una printf); tipo eq = ROW POLYMORPHISM E SUE APPLICAZIONI; OGGETTI = 77. Row variables e polimorfismo uniforme con row variables (row polymorphism) 78. Record estensibili: pseudo-sintassi, primitive e loro tipaggio 79. Oggetti in OCaml: sintassi e tipaggio; rappresentazione a run-time 80. Oggetti funzionali (immutabili) vs oggetti mutabili 81. Pre-metodi; pre-metodi come campi di oggetti. Confronto fra pre-metodi e metodi in OCaml 82. Metodi polimorfi in OCaml 83. Covarianza, controvarianza e invarianza nel subtyping 84. Come OCaml permette di gestire correttamente la varianza in presenza di tipi di dati astratti (di cui non è data l'implementazione) tramite annotazioni di varianza 85. Classi e inheritance in OCaml 86. Inheritance is not subtyping: essere in grado di fornire un esempio (p.e. in OCaml) che mostri un caso di inheritance per il quale la classe derivata non è un sottotipo 87. Il modificatore private di OCaml = TRAITS E TYPE CLASSES = 88. Metodi in Go: sintassi, semantica e vantaggi rispetto alle funzioni 89. Interfacce in Go e dynamic dispatch 90. Implementazione in Go dei metodi e delle funzioni che prendono in input variabili di tipo interfaccia 91. I traits di Rust: sintassi, semantica e implementazione 92. Il design space dei traits/mix-ins/etc. 93. Le type-classes di Haskell: sintassi e semantica 94. Type-classes per riconciliare la type-inference con l'overloading 95. Type-classes su costruttori di tipo 96. Schemi di implementazioni di type-classes: monomorfizzazione; via dynamic dispatch usando record (estensibili); via dynamic dispatch con type switch a run-time = REVERSIBLE COMPUTING = 97. Definizione di reversible computing 98. Applicazioni potenziali e già attuali del reversible computing 99. Techniche per il reversible computing in ambiente sequenziale 100. Il linguaggio di programmazione Janus 101. Dipendenza causale e reversible computing in ambito concorrente 102. Debugger reversibili in ambito sequenziale e concorrente = MONADS = 103. Definizione di monade e vantaggi nell'uso delle monadi 104. Le equazioni che una monade deve rispettare 105. Definizione di referential transparency 106. Implementazione di monadi classiche: Maybe, [], Reader, Writer, State 107. Altre monadi: IO, STM, ... = RUST = 108. Caratteristiche e motivazioni per Rust 109. Ownership e suo trasferimento 110. Borrowing mutabile e immutabile; references 111. Slices (mutabili e immutabili) 112. Lifetimes, loro dichiarazione e loro uso come bound per il polimorfismo parametrico 113. Smart pointers: Box, Rc, RefCell, Arc, Mutex, ... 114. Implementazione di uno smart pointer 115. Chiusure in Rust (e loro interazione con l'ownership e il borrowing)