Coding testuale ed open source, si puo fare!

Massimo Maria Ghisalberti - pragmas.org

Didattica Aperta 2018 - (14/09/2018)

Created: 2018-09-17 lun 09:30

Per seguire con il proprio dispositivo

Alcune premesse

  • Si è tutti più o meno concordi sulla validità dell'insegnamento della programmazione dei computer ai ragazzi (il cosiddetto coding), ma pochi si pongono il problema degli ambienti o dei metodi o della giusta età in cui iniziare. Al di là della polemica visuale si o visuale no i fattori importanti da prendere in cosiderazione sono anche l'indipendenza di tali strumenti da produttori software o hardware il cui scopo è la fidelizzazione ai propri prodotti.
  • Qui ci occuperemo di coding testuale, attività non particolarmente complessa con strumenti adeguati. Al contrario di quella visuale permette una visione più ampia del concetto stesso di Open Source e del codice sorgente come una sorta di storia, una narrazione di fatti ed eventi. Lo scrivere inoltre, porta ad una maggiore riflessione e comprensione del problema da affrontare con meno fasi di trial and error casuali.
  • Scrivere porta a rileggere e rileggere porta a comprendere.
  • Oltre ad alcune riflessioni verranno presentati due ambienti testuali Open Source:

Concetto di Open Source

  • Open Source significa poter accedere ai codici sorgenti dei software.
  • Open Source (OSS), Free and Open Source (FOSS) e Free/Libre Open Source Software (FLOSS) non sono la stessa cosa.
  • Free non significa necessariamente gratis.
  • Un Software Libero deve poter soddisfare quattro proprietà fondamentali: esecuzione, studio, ridistribuzione, miglioramento [https://www.gnu.org/philosophy/free-sw.it.html].

Considerazioni sull'esecuzione

  • Il software è il codice sorgente, questo implica che deve poter essere trasformato in un formato eseguibile liberamente.
  • Il software idealmente deve poter essere eseguito su più piattaforme possibili (multi piattaforma) senza limitazioni.
  • Se una piattaforma ne limita l'esecuzione la responsabilità è della piattaforma e non del Software Libero.
  • Non si può pretendere il file eseguibile di un Software Libero ma se questo c'è si deve poter accedere liberamente al suo codice.

Considerazioni sullo studio

  • Chiunque deve poter essere in grado di studiare ed analizzare il codice sorgente:
    • Controllo sulle falle di sicurezza.
    • Studenti per imparare linguaggi o tecniche implementative.
    • Adattamento alle proprie o di altri esigenze.

Considerazioni sulla ridistribuzione

  • Il codice sorgente deve poter essere ridistribuito.
  • È il codice sorgente a dover essere ridistribuito e non l'eseguibile.

Considerazioni sul miglioramento

  • Chiunque, analizzando e studiando il codice, può apportare miglioramenti od adattamenti.
    • devono essere redistribuiti nella stessa forma del codice originario.
    • devono permettere la trasformazione in eseguibile con le stesse annotazioni di cui sopra.

Possibili implicazioni del software FOSS e FLOSS per una pubblica amministrazione

  • Indipendenza dai produttori.
  • Ispezione del codice sorgente, per esempio per motivi di sicurezza.
  • Adattamento alle proprie esigenze e redistribuzione verso amministrazioni simili.
  • Risparmio in termini globali a lungo termine (probabilmente non nell'immediato).
  • Promozione e valorizzazione del lavoro piuttosto che sul prodotto.

Possibili implicazioni del software FOSS e FLOSS per la scuola pubblica

  • La scuola pubblica è una pubblica amministrazione.
  • Studio ed analisi del codice sorgente come artefatto umano.
  • Stimolo per la condivisione e la collaborazione.
  • Diffusione della conoscenza.
  • Valorizzare il concetto di eticità del software.
  • Altro?

Software proprietario gratis, falsi open source (FOSS/FLOSS)

  • Alcuni software sono distribuiti gratuitamente pur rimanendo proprietari
  • Alcuni software sono dei falsi FOSS/FLOSS, per esempio:

Computer come macchine per pensare

  • Gli elaboratori elettronici sono delle superbe macchine per pensare.
  • Sono macchine e questo non andrebbe mai dimenticato:
    • mezzo e non fine
  • Alcuni modelli mentali umani sono influenzati dall'utilizzo di queste macchine.
  • Esistono molteplici linguaggi di programmazione perché esistono tanti modi di pensare diversi.

linguaggi di programmazione

  • Ogni linguaggio di programmazione viene sviluppato seguendo una idea in qualche modo riconducibile ad un particolare paradigma.
  • Esistono linguaggi considerati puri e linguaggi impuri cioè che non seguono in maniera stretta (pura) il paradigma.
  • Alcuni linguaggi si ispirano a due o più paradigmi: linguaggi multiparadigma.
  • Alcuni dei macro paradigmi più ricorrenti:

linguaggi visuali

  • I linguaggi di tipo visuale sono comunemente dei DSL (domain specific language).
  • Utilizzati in ambiti ristretti (robotica, simulazioni, multimedia, giochi, etc…) od a scopo educativo.
  • Scratch [https://scratch.mit.edu/] segue il paradigma imperativo.
  • Snap! [https://snap.berkeley.edu/] è multi paradigma.
  • Luna [https://www.luna-lang.org/] è un linguaggio funzionale ad utilizzo generale.

effetto dei paradigmi di programmazione

  • L'utilizzo di un determinato paradigma di programmazione forma il modo di pensare.
  • Il passaggio da un paradigma all'altro è particolarmente oneroso e non sempre sufficiente.
  • Essendo i cosiddetti linguaggi Turing-completi equivalenti in espressività computazionale
    si tenderà a cercare soluzioni fantasiose ad un problema adatto ad un altro paradigma.
  • Il paradigma imperativo seppure molto utilizzato non è il migliore per l'insegnamento.
  • Quello funzionale e quello logico sarebbero più appropriati [http://minimalprocedure.pragmas.org/writings/Invito_alla_programmazione_funzionale/invito.html]

Programmazione logica

  • Descrittiva
  • Dichiarativa
  • fatti, regole, interrogazioni

Relazioni divine in Prolog

mortale(giovanni). /* giovanni è un mortale */
mortale(massimo)./* massimo è un mortale */
dio(massimo)./* massimo è un dio */
dio(tommaso)./* tommaso è un dio */

semidio(X) :- /* un semidio è sia dio che mortale */
   dio(X), mortale(X).

Interrogazioni delle relazioni divine

?- dio(massimo). 
true.
?- semidio(massimo).
true.
?- mortale(massimo).
true.
?- mortale(tommaso).
false.
?- semidio(tommaso). 
false.
?- dio(tommaso).
true.

Programmazione funzionale in breve

  • Dichiarativa per la maggior parte
  • Le funzioni nel senso matematico del termine sono il cardine strutturale.
  • Le funzioni sono oggetti di prima classe, quindi trattabili come valori.
  • Orientata alla trasformazione (riduzione, mappatura, applicazione) piuttosto che alla computazione.
  • Immutabilità (linguaggi puri ed impuri)
  • Tipizzazione forte (generalmente)
  • Programmazione funzionale, una semplice introduzione.

Alcuni esempi funzionali, una operazione di reduce

  • La funzione fold_left delle liste, ha bisogno di alcuni valori di input: una funzione da applicare, un valore iniziale ed una lista di qualcosa. Questa espressione avrà un valore di 15, la somma di tutti i numeri della lista. La funzione (+) viene applicata per ogni elemento.

    List.fold_left (+) 0 [1;2;3;4;5]
    
  • Definendo due funzioni e combinandole:

    let somma a b = a + b;;
    let applica_funzione f = List.fold_left f 0 [1;2;3;4;5];;
    
    applica_funzione somma;; (* -> Int: 5 *)
    
  • I codici sopra sono in OCaml, ma in Racket (un dialetto LISP):

    (foldl + 0 '(1 2 3 4 5))
    

Scala e Ruby perché Kojo e DuckQuack

  • Scala è un linguaggio multiparadigma a base funzionale e la stessa espressione precedente diventa:

    List(1,2,3,4,5).foldLeft(0)(_+_)
    // Oppure:
    List(1,2,3,4,5).reduce(_+_)
    // Oppure:
    (1 to 5).reduce(_+_)
    
  • In Ruby:

    [1,2,3,4,5].reduce(:+)
    # Oppure:
    (1..5).reduce(:+)
    

Espandiamo l'esempio in Scala

  • Definiamo una funzione applica_la_funzione_alla_lista_di_numeri con due valori di input: f (una funzione) e lista (una lista di numeri)

    def applica_la_funzione_alla_lista_di_numeri(
      f:     (Int, Int) => Int,
      lista: List[Int]) = 
      lista.reduce(f)
    
  • Poi alcune operazioni aritmetiche:

    def somma(a: Int, b: Int) = a + b
    def sottrazione(a: Int, b: Int) = a - b
    def divisione(a: Int, b: Int) = a / b
    def resto(a: Int, b: Int) = a % b
    def moltiplicazione(a: Int, b: Int) = a * b
    

Usiamo la funzione

  • Definiamo una variabile con una lista di numeri e poi applichiamo

    val lista = List(1, 2, 3, 4, 5)
    
    applica_la_funzione_alla_lista_di_numeri(somma, lista) // => 15
    applica_la_funzione_alla_lista_di_numeri(sottrazione, lista)// => -13
    applica_la_funzione_alla_lista_di_numeri(divisione, lista) // => 0
    applica_la_funzione_alla_lista_di_numeri(resto, lista)// => 1
    applica_la_funzione_alla_lista_di_numeri(moltiplicazione, lista) // => 120
    
  • Qualche dubbio sul perché l'applicazione di divisione restituisca 0?
  • codice dell'esempio

Somiglianze

  • Notate una certa somiglianza?

    def applica_la_funzione_alla_lista_di_numeri(
      f:     (Int, Int) => Int,
      lista: List[Int]) =
      lista.reduce(f)
    
    def applica_la_funzione_alla_lista[T](
      f:     (T, T) => T,
      lista: List[T]) =
      lista.reduce(f)
    

Ad un coderdojo, ragazzini tra i 10 e i 12 anni hanno compreso che una funzione è un valore e come tale può essere immagazzinata in una struttura dati, recuperandola in seguito.

kojo-0.png

Proviamo Ruby

  • La sintassi è più semplice, ma il concetto non cambia, il valore somma è una funzione anonima che viene applicata durante l'iterazione della lista:

    # literal syntax
    somma = ->(a, b) { a + b }
    
    somma_norm_syntax = lambda { |a,b| a + b }
    somma_norm_syntax_alt = lambda do |a,b| a + b end
    
    def applica_la_funzione_alla_lista(f, lista)
      lista.reduce(&f)
    end
    
    applica_la_funzione_alla_lista(somma, [1,2,3,4,5]) # => 15
    
  • codice dell'esempio

Perché un linguaggio è adatto al coding ed uno no

  • Se provo a fare la stessa cosa con l'ECMAScript (javascript moderno)

    const applyToList = (f, l) =>  l.reduce(f);
    const somma = (acc, valoreCorrente) => acc + valoreCorrente
    
    applyToList(somma, [1,2,3,4,5]) // => 15
    applyToList(somma, ["1",2,3,4,5]) // => 12345
    
  • Sia l'ECMAScript che Ruby sono linguaggi dinamici (il tipo è determinato a runtime) ma Ruby in questo caso emetterà un'eccezione (non si mischiano le pere con le mele) :

    Traceback (most recent call last):
      ...
    reduce_test.rb:1:in `+': no implicit conversion of Integer into String (TypeError)
    
  • L'ECMAScript non è un buon linguaggio per insegnare la programmazione.
  • Il PHP? Per certi errori dovete sapere l'ebraico: T_PAAMAYIM_NEKUDOTAYIM

A che serve questa lista di piccoli esempi?

  • L'operazione di riduzione (o folding) non è complessa come può sembrare.
  • il concetto di applicare qualcosa a qualcos'altro è una operazione naturale per l'uomo, siamo abituati all'utilizzo di strumenti.
  • la cooperazione piuttosto che il mero ordine di un linguaggio imperativo è educativa.
  • I concetti di astrazione, genericità e composizione sono favoriti da questo tipo di operazioni.
  • È praticamente impossibile affrontare queste problematiche con Scratch che non ha il concetto di funzione
  • Se il visuale è indispensabile per voi, usate Snap! [https://snap.berkeley.edu/]

Papert e Wings

  • Il LOGO è un dialetto LISP sviluppato da Wally Feurzeig, Cynthia Solomon e Seymour Papert.
  • La Wing ha studiato il lambda calculus come dichiara: …we learned lambda calculus. And I was just blown away! I said, "Wow! This is something I've never seen before and I really like it." (…) And so then, I decided to switch from majoring in electrical engineering to majoring in computer science. (http://www.women.cs.cmu.edu/What/Interviews/jeannetteWing.php)
  • La Wing a pagina 3 del documento https://www.microsoft.com/en-us/research/wp-content/uploads/2012/08/Jeannette_Wing.pdf cita espressamente: ML e Haskell, insieme a Java e Python.
  • Pare che i due più conosciuti attori del pensiero computazionale facciano parte del mondo del paradigma funzionale.

Kojo e Scala

Kojo

  • Integra Geogebra che è pilotabile via codice Scala.
  • Integra Jfugue per esplorare la composizione musicale digitale.
  • Turtle Graphics tradotto i varie lingue.
  • Tracciamento dell'esecuzione del codice
  • Editor con completamento e suggerimenti
  • Arduino

Area di lavoro

kojo-1.png

Area di tracciamento delle istruzioni

kojo-2.png

Point and Click Visual programming (?)

kojo-3.png

Tartaruga italiana

kojo-4.png

Suggerimenti e completamento del codice

kojo-5.png

Questo o quello

  • Grazie al linguaggio Scala, si possono progettare nuove strutture

    def questo_o_quello(test: Boolean) (questo: => Unit) (quello: => Unit) {
      if(test) questo else quello
    }
    
    val n = 2
    
    questo_o_quello(n > 3) {
      println("è questo")
    } {
      println("è quello")
    }
    
  • questo_o_quello diventa un analogo della struttura if then else ma di tipo imperativo senza restituire quindi valori.
  • codice sorgente

Risorse

DuckQuack e Ruby

  • L'ho scritto io, il codice sorgente è qui: https://gitlab.com/minimalprocedure/DuckQuack
  • Non vuole essere il Kojo per Ruby e né vuole competere.
  • Nato per dimostrare come se un ambiente non c'è si può sempre fare, dal mio punto di vista è pensiero computazionale.
  • Usa Ruby, un ottimo linguaggio multi paradigma dinamico.
  • Ruby è molto adatto per la metaprogrammazione.
  • È praticamente quasi tutto traducibile, dall'interfaccia alle istruzioni tramite configurazioni.
  • È espandibile facilmente con se stesso, Ruby è un linguaggio interpretato ed il sorgente è sempre accessibile.
  • È multi piattaforma e funziona dove la JVM funziona (come Kojo).
  • È perennemente in beta, nessuna versione stabile uscirà mai.

La papera, niente tartarughe

duck-1.png

Codice di test per le traduzioni

duck-2.png

Spirali connesse

duck-3.png

Che tempo fa?

duck-4.png

Graphical User Interface

duck-5.png

Graphical User Interface

duck-8.png

Musica e bottoni con JFugue

duck-9.png

Web server

duck-6.png

Database SQlite

duck-7.png

Risorse

Calcolo del Massimo Comun Divisore e Minimo Comune Multiplo con l'Algoritmo di Euclide

  • Dati due numeri naturali a e b, si controlla se b è zero (questa prima fase rientra ovviamente nell'ambito di un uso moderno dell'algoritmo ed era ignorata da Euclide e dai suoi predecessori, che non conoscevano lo zero). Se lo è, a è il MCD. Se non lo è, si divide a / b e si assegna ad r il resto della divisione (operazione indicata con "a modulo b" più sotto). Se r = 0 allora si può terminare affermando che b è il MCD cercato, altrimenti occorre assegnare a = =b e =b = r e si ripete nuovamente la divisione. L'algoritmo può essere anche espresso in modo naturale utilizzando la ricorsione in coda.

Scratch

scratch-mcm.png

Snap!

snap-mcm.png

Scala

def MCD(number1: Int, number2: Int): Int = {
  val rest = number1 % number2
  if (rest == 0) number2
  else MCD(number2, rest)
}

def mcm(number1: Int, number2: Int): Int = {
  (number1 * number2) / MCD(number1, number2)
}

Ruby

def mcd(number1, number2)
  rest = number1 % number2
  rest == 0 ? number2 : mcd(number2, rest)
end

def mcm(number1, number2)
  (number1 * number2) / mcd(number1, number2)
end

Un ambiente educativo per il coding dovrebbe essere

  • Open Source e meglio se FLOSS.
  • Deve usare un linguaggio completo per essere scalabile.
  • Deve poter essere espandibile ed adattabile nello stesso linguaggio che si sta imparando.
  • Non deve in nessun modo limitare lo studente e non deve essere frustrante.
  • Deve essere multi piattaforma sia nell'applicazione che nel linguaggio.
  • deve essere localizzato? (lo chiedo a voi)
  • Deve essere moderno.
    • [polemica on]
      • lasciamo le tartarughe (ed i gatti) a vivere in pace
      • se proprio dobbiamo allora meglio Alonzo: alonzo.png
    • [polemica off]

Implementiamo questo in Scala o in Ruby?

\begin{equation} lev_{a,b}(i,j) = \begin{cases} max(i,j) & \qquad \text{se } min(i,j) = 0 \\ min \begin{cases}\; lev_{a,b}(i - 1,j) + 1 \\ lev_{a,b}(i,j - 1) + 1 \\ lev_{a,b}(i - 1,j - 1) + 1_{(a_{i} \neq b_{j})} \\ \end{cases} &\qquad \text{altrimenti} \end{cases} \end{equation}
  • Per compito a casa per i più bravi, gli altri guardino la soluzione

Curiosità

  • Elliot Alderson (Mr Robot) usa Ruby 😃
elliot.jpeg

Si può fare!

frankenstein_junior.jpg

Contatti e ringraziamenti.

Licenza Creative Commons Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale.