tuProlog / 2p-kt-presentation

0 stars 0 forks source link

Enrico's notes #15

Open gciatto opened 3 years ago

gciatto commented 3 years ago

The following notes are relative to version 0.32.0 of the slides:

slide 23: is è veramente senza parentesi? Tutti gli altri predicati le hanno -> se, come penso, tutti gli isXXX sono proprietà, meglio dirlo subito in generale
slide 24: equals(Term,Boolean) ?  il bool è il flag? (specificherei)
slide 26: ottimo, aggiungerei una 26 bis con l'equivalente Java
slide 28: l'uso di BigInteger determina problemi di performance? se avessi tali concern, potrei evitarlo?
slide 30: typo: dovrebbe essere "r" in tutti gli esempi, "i"
slide 35: in ga.toString(), metterei nel commento // "g(a,1)" fra virgolette;
          stessa slide: forse converrrebbe specificare i tipi in alcuni casi, es FXa1Y, per far capire di che tipo siano
      ciò in particolare per evidenziare la differenza fra le varie toString, sopra e sotto
slide 39: comple name?
slide 40: anche qui, is senza () è voluto?
slide 43: l'ultima arity è null.. capisco che N fosse unbound però è proprio bruttino, a maggior ragione in un ling come kotlin che aborrisce la NPE e anela alla null safety
      Andrebbe rivisto il tipo di ritorno.. se fossi in Java ti direi un OptionalInt, qui è vero che l'hai definito come Int? però è brutto forte..
      Usare Var.anonymous() come nella slide 41 non sarebbe più coerente ? Vedi anche slide 60, stesso pbm con le clause
slide 46/47: quel "plus T" non è molto chiaro, rifraserei
slide 51: il titolo della slide afferma di mostrare unfold(..) ma in realtà non esiste quel metodo: si usa unfoldedSequence()
      Più in generale, nelle slide "teoriche" si cita sempre anche unfold, ma non c'è mai negli esempi
slide 55: forse richiamerei cosa sia un logic set, ovvero: ammette duplicati? anche per differenziarlo dalle liste
      NB: l'unico momento in cui questo salta fuori è alla slide.. 112 ! Meglio dirlo qui
slide 57: l'esempio sarebbe più completo aggiungendo il caso di elementi duplicati - restano? sono assorbiti? come li gestisce? (v. anche slide 112)
slide 60: problema null, vedi commento slide 43
sldie 61: "anchestor" si scrive senza h :) -- anche slide 86 e 90
sldie 62: "integer" non sarebbe meglio si chiamasse "one" come in altri esempi precedenti? sia per coerenza interna che per chiarezza
slide 64/65: perché ci sono costanti specifiche per 0,1,-1 (nonché 1/2 e 1/10 nei reali)? Andrebbe dato almeno il razionale della scelta, appare strano
slide 66: appare disuniforme avere due valori per falso e solo uno per vero --> se hai fail, non dovresti avere anche success, inteso come true?
slide 67: there is INTENTIONALLY no way.. (v. anche slide 85 dove questo aspetto è ripreso)
      Inoltre qui andrebbe forse spesa qualche parola per spiegare che la factory, sempre intenzionalmente, non adotta un approccio value-based,
      quindi ogni Var.of produce una nuova, diversa fresh variable (al contrario immagino di ciò che accade con i numeri.. esatto?) --> cfr slide 70
      NB1: forse la slide 70 andrebbe anticipata, prima di cominciare tutta la carrellata di termini
      NB2: poi alla slide 87 si scopre che c'è un mondio dietro.. converrebbe anticiparlo, dicendo che però ci sarà modo, tramite il concetto di Scope,
      di definire variabili da riusare più volte
slide 68: ..using the provided functor.. (che però è un Term.. o si mette il nome o magari si precisa, anche se è semi-intuitivo)
slide 70: simile issue ma meno scontato: anche qui Term sarebbe the "last argument" menzionato? Inoltre c'è un typo, "be" --> "by"
slide 71: è necessario specificare last=?
slide 72: perché le tuple devono avere sempre almeno due elementi? capisco che è quello l'uso inteso, però.. why?
      Inoltre: nelle altre slide, subito dopo c'è l'esempio; qui (e nelle seguenti) invece no, perché?
slide 73: "all the terms"... e se c'erano duplicati che fa? -> specificare + mettere esempio
slide 74: brutto che un argomento possa essere null (vedi discorso sopra) e non necessario, dato che se non è null c'è già la factory Rule.
      Non sarebbe meglio sostituire questo con Directive.of, dove il primo argomento non ci sia?
      Altrimenti, o in aggiunta, meglio avere DUE Clause.of, uno a un argomento e l'altro a due argomenti, ma in cui nessun arg sia mai null
      Inoltre: al di là della mera questione implementativa, importa all'utente sapere che dietro viene creata una Tuple?
      Se è un fatto implementativo non deve trasparire, meglio non menzionarlo neppure. Se invece ha un'altra valenza allora deve trasparire, ma allora va anche spiegato e detto diversamente
slide 70: molto imporatante, probabilmente da anticipare prima della carrellata di termini, altrimenti (v. slide 67) si creano dubbi evitabili
      Inoltre: alla luce della definizione, due strutture con variabili non potranno mai essere uguali a meno che non contengano riferimenti alla stessa identica variabile, right?
      Magari converrebbe enfatizzarlo e mostrarlo in un esempio, just to be sure
slide 75/76/24: trovo poco espressivo ed error-prone usare un boolean per cambiare il comportamento, pur nel contesto kotlin in cui i parametri possono essere named all'atto della chiamata. 
      O facciamo due metodi distinti (equals vs same, o analogo) oppure come minimo servirebbe un enumerativo al posto del boolean, con costanti "parlanti" e.g. TermComparison.EQUALITY 
      vs TermComparison.IDENTITY, o qc di analogo. Così tra l'altro incorporeremmo anche Java, che nell'approccio attuale diventa hard to use perché senza parametri named, un boolean
      è sostanzialmente privo di semantica
slide 77: typo, numberss (con due s) 
      Inoltre, mi riallaccio a quanto sopra: brutto avere un metodo ad hoc, structurallyEquals.. con un enumerativo a tre valori, sarebbe integrabile nella equals/2 sopra
slide 78: l'esempio conferma che non è user friendly, t1.equals(t2) è un po' misleading con questa semantica, ancorché giustificabile. Meglio sarebbe una visione più chiara e integrata.
      Inoltre: t3 è costruito ma mai usato nell'esempio, così ha poco senso.
        println (t1.equals(t2)) // false
        println (t1 == t1) // alias for the above
        println (t1.equals(t2, TermComparison.IDENTITY ) ) // false
        println (t1.equals(t2, TermComparison.EQUALITY )) // true
        println (t1.equals(t2, TermComparison.STRUCTURAL_EQUALITY) ) // true
slide 80: by arity --> toglierei by, c'è già nella frase principale
slide 84: farebbe piacere un mini-esempio commentato
slide 85: v. slide 67
sldie 86: "anchestor" si scrive senza h :) -- anche slide 61 e 90
      inoltre, la scritta "This is wrong" dovrebbe essere la prima riga in alto, altrimenti è misleading. Scriverei "Wrong version": e poi sotto invece "Correct version"
      Anche qui potrebbe valere la pena di mettere un piccolo "forward pointer" che eviti l'obiezione tipica = che così è scomodo doversi portare in giro ref a variabili da riusare,
      preavvisando che esiste all'uopo il concetto di Scope. Che infatti poi giunge alla slide 87
slide 88: typo: manca chiusa parentesi nella prima riga
sldie 90: "anchestor" si scrive senza h :) -- anche slide 61 e 86
      Qui ho un problema di immediatezza della sintassi di creazione degli Scope. A prima vista, leggendo la slide 89, tutto filava. Ma poi, vedendo l'uso concreto, trovo
      innaturale scrivere che c'è uno scope empty per poi, subito dopo, riempirlo - ossia in definitiva crearlo "non empty" ! -- è misleading, anche se concettualmente corretto
      Proposta da discutere: dato che è altamente improbabile che uno voglia crearsi uno scope vuoto per il puro gusto di lasciarlo vuoto, una sintassi forse meno perfetta
      dal punto di vista astratto ma più naturale quando vai a usarla potrebbe consistere nel rinominare "empty()" in "new()" oppure "of" (meglio): così la frase diventerebbe:
        val rule : Rule = Scope.new { // oppure: Scope.of
            ruleOf (
                structOf (" anchestor ", varOf ("X") , varOf ("Y")) ,
                structOf (" parent ", varOf ("X") , varOf ("Z")) ,
                structOf (" parent ", varOf ("Z") , varOf ("Y"))
            ) // anchestor (X_1 , Y_2 ) :- parent (X_1 , Z_3 ), parent (Z_3 , Y_2).
            }
      DIverso il caso dell'esempio 2, dove, essendo su righe distinte, è più tollerabile l'uso di empty() -- però un bell'of risolverebbe egregiamente anche qui.

slide 92: to their corresponding Terms (con la s finale)
slide 93: non avevo capito, e ho capito solo dall'esempio in slide 97, che chiamare plus/minus i metodi avrebbe abilitato l'uso degli operatori +/- perché Substitution deriva da Map.
      Forse non sarebbe sbagliato dirlo, è un "plus" non da poco
slide 95: possibile svista in un pedice: non sono completamente certo ma mi suona strano che nel secondo caso Yi = t'j (i era l'indice delle X, dovrebbe forse essere Yj)
slide 96: typo, c'è un errore nell'esempio, riga 3, variabile u2: manca il funtore f nella struct
      Inoltre, per non confondere il lettore, a quel punto non chiamerei proprio f la variabile fail della riga successiva --> oppure il funtore sopra non si chiami f, magari meglio
      Infine: s2, a cui è stato aggiunto anche fail, ora è solo fail, ossia ha "perso" i precedenti binding. Questo può apparire "innaturale" in un operatore +, che tipicamente
      aggiunge ma non toglie. E' una semantica giusta ma associata a un operatore potenzialmente misleading, che si comporta in modo "innaturale" rispetto al behaviour atteso
      di una "somma". Peraltro introduce un corner case interessante: che succede TOGLIENDO (con minus) il fail a una substitution? Andrebbe detto (prima) e mostrato nell'esempio (qui)
slide 99/100: ho un dubbio amletico sulla correttezza del lanciare eccezione in questo caso, ossia del considerare "senza senso" l'applicazione della sostituzione fail a un termine.
      Non ricordo cosa dicano i sacri testi ma .. non è che dovrebbe venir fuori il famoso _|_ ? Nella gerarchia dei termini, c'è il "termine non termine"? Cmq così è naturale da usare,
      tanto stiamo parlando di un corner case che probabilmente non si verificherà spesso. MA è la solita questione: se per un qualche problema si crea una sostituzione fail dove
      di norma dovrebbe essercene una ok, lanciando eccezione si ammazza il programma (salvo che ci siano catch, improbabili se la cosa era inattesa). Vero, è un bug, quindi è pure
      giusto: dopo tutto, propagare un fallimento non sarebbe correttissimo, però... mmhhhh
side 101: salta fuori dal nulla la sintassi con le [..] (ultima riga, r4). Immagino si sfrutti il fatto che siano map, ma la cosa lascia interdetti perché sopra invece si è usato apply.
      Servirebbe forse più uniformità nell'esempio
slide 103: typo nell'ultima riga, "is" c'è due volte
slide 107: aborrisco i due casi in cui si ritorna null, c'è una chiara violazione di precondizioni quindi dovrebbe lanciare eccezione
slide 108-111: belle.. ma ci si perde. Servirebbe mettere a fianco un esempio: a sinistra si illustra la cosa, a destra la si esemplifica. Altrimenti ci sono semplicemente troppi casi 
      e sottocasi per starci dietro e coglierli tutti
slide 112: finalmente si chiarisce che i set non ammettono duplicati, ma andava detto molto prima (cf. slide 57)
      Rifraserei la spiegazione: dire prima che è immutabile, poi che ci sono operatori add/remove, poi che in realtà creano una copia è corretto ma misleading.
      Basterebbe dire, mentre si introducono add/remove, che "by creating a new OperatorSet", o qc di simile
slide 113-118: qui andrebbe invertito l'ordine, ovvero prima andrebbe detto che ci sono un tot di set predefiniti, ELENCANDOLI SUBITO; poi andrebbero presentati uno per uno, come già si fa.
      In pratica ci vorrebbe una slide - probabilmente la 119 - prima della 113
slide 122: attaived..?
slide 124: aim to + infinito, aimed at + gerundio, non il mix :)
slide 124-131: anche qui anticiperei qualche esempio, altrimenti 7-8 slide di manualistica senza vederne l'applicazione diventano poco utili ci si perde
      Ideale sarebbe partire dalla slide 131, magari ampliandole (=facendone due o tre) e subito dopo spiegare quei formatter che si usano e le loro opzioni. My two cents of course.
slide 132+ (eccezioni): vedi dubbi sopra, ossia il dubbio di cui alle slide 99/100 e l'opportunità, viceversa, di aggiungere magari un'eccezione per il caso della slide 107
slide 140: avrebbe bisogno di due parole di spiegazione sotto, per chiarire dove sia esattamente l'effetto del cached unificator. Ossia: al di là del fatto che abbia cachato, dove
      sta il guadagno? Dove lo vedo? Dall'esempio non mi sembra si veda
slide 142: molto carina, ma per maggior chiarezza chiamerei quell'unificatore "myUnificator"
slide 143: molto carino :)
gciatto commented 3 years ago

These notes are relative to version 1.1.1 of the slides:

======= 12/05/2021 su nuove slide v. 1.1.1 =======
NB è cambiata la numerazione, non mi ci raccapezzo: ho solo capito che la vecchia slide 90 ora è la 101, ma non so dove abbia inserito nuove slide prima.
===================================================

OCCHIO: tutti i link cliccabili portano nel posto sbagliato, es slide 146 nuva, cliccando sulla riga evidenziata si zompa 200 slide avanti

slide 143 nuova:  resto perplesso sul '_0' emesso per tutte le variabili, non le distingue. Non dovrebbe essere _0, _1, ... ?
    Vale sui primi due formatter. Altrimenti sembrano la stessa variabile..
    Inoltre, sempre nell'esempio: il termine '$VAR' ha un significato particolare? Se no, se è solo un esempio di termine "strano", non aiuta la comprensione aver scelto proprio "VAR" come nome.
    Meglio qualcosa di diverso, agnostico, privo di qualsiasi pre-significato inteso.
    Se invece avesse un significato specifico andrebbe detto perché da qui non emerge.

slide 144-146 (eccezioni): vedi dubbi sopra, ossia il dubbio di cui alle slide 99/100 (vecchia numerazione) e l'opportunità, viceversa, di aggiungere magari un'eccezione per il caso della slide 107 (ora 119, penso)

slide 154: avrebbe bisogno di due parole di spiegazione sotto, per chiarire dove sia esattamente l'effetto del cached unificator. Ossia: al di là del fatto che abbia cachato, dove
      sta il guadagno? Dove lo vedo? Dall'esempio non mi sembra si veda

slide 156: carino l'esempio del custom unificator, ma per maggior chiarezza chiamerei quell'unificatore "myUnificator", perché "unificator" è un po' vago..
slide 157: (infix) molto carino :)

--slide 158 e seguenti (collections)
slide 162: non dice cosa sia un RetrieveResult e questo rende di difficile comprensione il successivo esempio alla slide 169.
    Aggiungerei: "returns the pair (retrieved element, rest of the collection) as a suitable RetrieveResult instance"
slide 169: esempi retrieve: ok, ma rimuovere proprio f(1) con retrieveFirst può far pensare che rimuova il primo elemento, che solo casualmente è f(1), non "il primo che fa match".
    Suggerirei di rimuovere f(2), così si capisce meglio. Richiamerei anche la spiegazione sopra (cfr commento alla slide 162)
    Inoltre, servirebbe un ulteriore esempio da inserire nella slide 170: che succede se faccio retrieve f(X)? Lì sì che si capisce cosa significhi "retrieve FIRST".
    Se poi i fatti fossero più sofisticati, es. f(a,1), f(a,2), f(b,3), f(b,5), f(c,4), si potrebbe fare una retrieve(f(b,X)) e vedere cosa restituisce.
    [ vedi anche slide 182, discorso analogo ]

slide 177: aggiungere che plus si rimappa sull'operatore + (forse scontato ma non fa male ribadirlo, non tutti sono familiar con Kotlin a questo livello, e ogni linguaggio fa a suo modo a questo riguardo)
slide 178: occorre specificare cosa sono i dati dei due casi concreti Success e Failure, soprattutto il primo
slide 182: vedi commento alla slide 169
slide 185: English --> composed OF (by si usa solo per i brani musicali, dove c'è un autore)
slide 186: "implemented in Kotlin" -- necessariamente? solo Kotlin? o volendo anche Java, Scala, etc.?
slide 193: carrying some variableS

--nota preliminare alla osservazioni seguenti: ANTICIPARE LE DUE SLIDE 206/7! altrimenti non si capisce nulla

slide 197: compare dal nulla Solver.classic che NON era presente né nell'UML precedente né nelle descrizioni. Immagino chi sia, ma non è mai detto che ci siano dei solver "predefiniti" - quali?
      Inoltre andrebbe detto che l'identiticatore staticKb si riferisce alla proprietà omonima.. capisco sembri tautologico ma non lo è..
slide 199: idem con patate, qui compare anche Solver.classic.solverOf che non si capisce cosa faccia di diverso dai solverWithBuiltins precedenti.. è un alias per 0 builtins? (cfr. slide 201)
slide 200: occorre un commento sotto che contestualizzi la scelta di 1 ms - potrebbe essere troppo poco in una macchina, yielding no solutions, o più del previsto in un'altra, yielding magari 2 o 3 soluzioni.
      Scritto così, il risultato è indeterminabile a priori...!
slide 201: vedi commento alla slide 199, va chiarito cosa fanno queste factory
      Inoltre: va chiarito il tipo di solution.exception: se lo converti in HaltException per beccare l'exitStatus, significa che era qualcos'altro, più generale => diciamolo
slide 200 vs 202: a volte si usa factOf, a volte Fact.of: non ci si raccapezza più. Sono la stessa cosa? Non lo sono? Qual è la ratio d'uso?
    (vedi anche slide 205)
slide 204: scritto così, la questione mutable/immutable solvers è tutto fuorché chiara. Riformulerei tutta la descrizione, così:
     solvers are immutable by users, and only expose properties for the inspection of their state
        - e.g., their state changes, but only because of internal resolution steps, not due to external actions
     mutable solvers, instead, expose methods enabling users to explicitly alter the solver state

slide 205: qui di nuovo si usa solverOf MA POI si caricano anche dei builtins.. come detto sopra ci sono forse troppi modi diversi, ma simili, di costruire le cose: non si coglie la ratio di quando usare l'uno e quando l'altro

slide 206/7: ADESSO lo dice?

slide 208: non è chiaro cosa siano solve-classic (col trattino, in italic) e la consorella solve-streams (non è mai stato detto)
    inoltre, dye typo: "accessbile" --> accessible; e nel box rosa, SolveFactory --> SolverFactory (anche slide 313)
    MA SOPRATTUTTO: qui manca l'UML che mostri la gerarchia, senza la quale l'esempio alla slide 210 non si segue compiutamente (perché usa la classe astratta SolverFactory)
slide 209: vale il commento alla slide 205, ne presenterei UNO SOLO, il resto declassiamolo a scelta interna. Manterrei Solver.classic e Solver.streams, e renderei nascoste le due classi XXSolverFactory

slide 210: va sviluppato con qualcosa di più, perché così si intuisce appena ma dà troppo per scontato, è un esempio che non esemplifica

slide 212: English: mancano due "it" --> it is currently focussing / it has constructed so far

slide 214: formulazione della frase altamente misleading, quel novel (Mutable)SOlver fa pensare che si crei un mutable solver sempre, invece intende solo con il factory method mutable. Rifraserei opportunamente

slide 216: ... or register/2 (the latter, from the :oop-lib module)
slide 217: i mutable solvers possono SOLO ricevere la loro KB dinamicamente, o ANCHE prima, come i solver classici? Scritto così è ambiguo -> chiarire

slide 218: scritto così, l'esempio è potenzialmente misleading perché può far pensare che le due println in qualche modo dipendano dalle due teorie definite inizialmente, che invece NON sono state ancora usate.
    Opportuno scambiare l'ordine delle righe: PRIMA le tre righe col solver+le due println, POI le definizione di theory1 e 2, che socì verrebbero usate subito dopo. Lindo e chiaro :)

slide 220: typo: provisioing --> manca una N
slide 221: typo: proprity --> priority
slide 222: opportuno aggiungere un commento, o nel codice o sotto, circa il fatto che il predicato g/1 viene trasferito d'autorità nella dynamic KB proprio a causa della direttiva, cosicché la dynamicKB non è vuota e la staticKB non contiene g/1

slide 225: come 186, solo in Kotlin?

slide 226: qualcosa non torna.. Jiesava? Inoltre il Camel Case non è quello, anzi qui sembra tutto minuscolo!
    A parte ciò, servirebbe spiegare meglio la NECESSITA' di questi alias, oltre a darne la sintassi: a che servono? Che bisogno soddisfano? Non è scontato, uno non se lo aspetta.. motivare!

slide 230: il commento nelle functions ha un doppio "here" che probabilmente è un typo
    Inoltre: scrivere "alias.of.the.lib" coi dots fa pensare che sia una naming convention: se lo è, va spiegato meglio perché non si capisce (cfr se non alla slide 235 dopo, NDR)
    altrimenti a questo stadio eviterei: meglio un commento come negli altri casi sotto, così è anche uniforme, poi il dettaglio emerge dopo (slide 235) e lì si capisce
slide 231: ultimo bullet, IP? In generale eviterei acronimi non ovvi
slide 232: "lazily enumerated" intende LE SOLUZIONI? Non è scritto -> va precisato (si potrebbe pensare fossero le primitive, visto che si parla di loro, ma parrebbe strano)

slide 234: "in code" ..? non c'è codice --> va nella slide seguente 235, penso

slide 235/6: magari due righe di spiegazione/commento in più ci starebbero.. chi legge deve indovinare sia che predicato sia, sia l'uso di certe strutture (es. sequenceOf) che magari sono state presentate, ma centinaia di slide fa
    In particolare, slide 236: perché usi BigInteger.ZERO invece di Integer? (cfr anche slide 246) Serve un commento per il lettore altrimenti ci si perde

slide 242: ma println non dovrebbe stampare " a :- true. b:-true. c:-true", secondo quanto mostrato in precedenza? Ora invece il ":-true" viene omesso..?
    Inoltre sarebbe utile un commento alla riga chiave del codice perché ci sono molte cose date per scontate.. agevolerei il povero lettore

slide 243: più che "Problem" intitolerei il box "Issue", perché non è un problema (di 2P o di altri), è una caratteristica che serve supportare per rispondere a un'esigenza del mondo

slide 246: ok, ma perché usi BigInteger.ONE invece di Integer? (cfr anche slide 236) Serve un commento per il lettore altrimenti ci si perde
    Inoltre occorrerebbe commentare anche il caso else: perché qui nopn lanci eccezione se l'argomento non è intero? Stai definendo next(pippo) come pippo? Alquanto arbitrario, per lo meno va detto...

slide 247: typo: evalued --> evaluated

slide 250: anche qui il codice avrebbe bisogno di qualche commento, la parte chiave (il when) è difficile da seguire, è molto dato per scontato che chi legge sappia/ricordi tutto

slide 251: nell'ottica di un manuale comprensibile a tutti, eviterei "prosumers" che come termine è un po' aulico. Sostituirei com "both consumers and producers"
    Soprattutto:cos'è MP??

slide 252: univoke non esiste! -> unique, unambiguous

slide 256: if the channel is over --> has reached EOF (o altra formulazione: is over non mi pare si possa dire qui, non è un'attività..)

slide 258: riformulerei l'ultima frase, solo perché dire "out of" in un InputChannel fa un po' specie --> from
    Inoltre: nel caso JS quindi cosa si può usare in alternativa? Viene spontaneo chiederselo, visto che poi per gli output il mapping su Console.log e Console.error invece c'è

slide 259: typos nel commento --> blockS until a line IS prompted

slide 262: ChannelStore o ..chi? Il titolo della slide si riferisce a una entità che NON C'E' NELLO SCHEMA

slide 266: servirebbe un commento per stdOut, la lambda con quell'it non rende chiaro chi sia it in quel contesto, si deduce solo dalle stampe dopo ma non è chiarissimo

slides 268-9-270: ma se NotableFlag serve solo per il builtin, perché non si chiama BuiltinFlag..?

slide 274: typo: perfomed (manca una R)
slide 275: typo: prints NOTING -> Nothing

slide 279: dire che l'eccezione "provokes" un certo evento mi sembra fuorviante, solitamente è il contrario: viene lanciata in risposta a tale evento, che quindi è già accaduto per cause esterne

slide 296: allargare figura, è illeggibile
slide 298: comes with 4 "more" abstract sub-classes -- more? Non ha senso, sono sottoclassi.. se invece era "4 more", è inutile --> 4
    Inoltre, "to be preferred" fa pensare che sia solo un consiglio, ma dal contesto sembrerebbe di fatto l'unica scelta coerente --> to be CHOSEN

slide 304: dubbio riguardo al TypeError: il secondo argomento può anche ssere variabile, scritto così è riduttivo (per non dire errato)

slide 313: anche qui typo SolveFactory -> SolverFactory (manca la R)
    inoltre, altro typo "are no excetion" (manca la P)
    infine, anche qui non è chiaro il modo di scrivere ":solve-classic" e ":solve.streams"

=== arrivato alla slide 318: INIZIARE MACCHINA A STATI, solve-classic module