Category Archives: programmazione

SICP in Python

nikon-small-world-glycerin-based-soapy-solution
Cosa non si trova ontehtoobz!
Recentemente José Alonso posta questo cinguettio: SICP (Structure and Interpretation of Computer Programs) in Python.
Non è una novità assoluta, l’ho anche inserito nella pagina dei manuali di OKp: Composing Programs.
Ma siccome SICP è uno dei miei tormentoni preferiti oggi guardo e riferisco. Viene da uno corso (uno di quelli iniziali) per gli informatti, giù a Berkeley. Seguendo i link si trovano cose interessanti, p.es.:

This semester, 61A will be taught using the Python 3 programming language. Python is a popular language in both industry and academia. It is also particularly well-suited to the task of exploring the topics taught in this course. It is an open-source language developed by a large volunteer community that prides itself on the diversity of its contributors.

In previous semesters, this course was taught using the Scheme language, a dialect of Lisp, which itself dates back to 1958, making it the second-oldest “higher-level” programming language that is still in use (after Fortran). Lisp and Python are similar in many ways. In fact, Lisp popularized many of the features that make Python a great language. Python has excellent library support for a vast range of application areas. Knowing Python will help you pursue your future programming interests, wherever they may lead you.

E anche

Learning Cooperatively
With the obvious exception of exams, we encourage you to discuss all of the course activities with your friends and classmates as you are working on them. You will definitely learn more in this class if you work with others than if you do not. Ask questions, answer questions, and share ideas liberally.

Since you’re working collaboratively, keep your project partner and TA informed. Questa è scontata ma forse –OK, perso[nale], non leggete il mio commento.

Cooperation has a limit, however, and in 61A that limit is code. Homework problems should be completed and turned in individually. Feel free to discuss the problems with others beforehand; just submit your own work in the end. Parole sante! valgono anche per me quando affronto gli esercizi di SICP.

Copying all or part of another person’s work [… is a form] of cheating and will not be tolerated.

Rather than copying someone else’s work, ask for help. You are not alone […]!

Peccato non essere un giovane pischello californiano! 😦

OK, ma il manuale?
Non l’ho esaminato in dettaglio; non ho fatto gli esempi proposti (anche perché mi sembrano chiari e non sono difficili, almeno all’inizio).
Per non auto-spoilerarmi (ahemmm… a volte seguo la moda della post-truth) non sono andato oltre al cap. 1. Nel PDF c’è qualche codice HTML che è rimasto invece di essere interpretato, ma sono pochissimi e facili da sgamare.
Segue abbastanza fedelmente l’originale in Scheme, in qualche punto è aggiornato; in qualche punto Python impone di scostarsi, comunque è fatto bene.

Forse per quanto detto nell’intro al corso (e da me riportato sopra) mancano gli esercizi che il SICP originale propone.

Mi sembra usabile per imparare sia la programmazione (un po’, mica tutto) sia Python (un po’, mica tutto). E gli esercizi mancanti andate a recuperarli di là e fateli. Io invece continuo per la vecchia via, sono vecchio e abitudinario.

Anche se c’è sempre il solito rischio.

:mrgreen:

Annunci

Modifiche – a volte NO!

knuth-c60

Un post che è anche un proposito per l’anno nuovo 😉 Ma non solo, anzi. E sì, scontato, tutte cose risapute 😳

Comincio con una storiella: un programmino, meno di mille righe di codice Python recentemente, occasionalmente, crashava misteriosamente. Un bug, uno dei tanti, ovviamente. Il guaio è che non era facile riprodurre il bug, io non ci sono riuscito mai.
Solo un appostamento prolungato (ruolo da agente segreto infiltrato con occhiali da sole, completo nero e barba finta sopra quella vera) ha consentito di stanare il colpevole, anzi due di loro. Recidivi come si vedrà tra breve.

Quando si scrive uno script per semplificare calcoli lunghi e tediosi spesso si fa con specifiche che non sono ottimali, anzi tutt’altro. La cosa migliore è vedere qualche caso tipico fatto a mano con l’utente che sa tutto. Ma a volte l’utente sa anche troppo: trova un caso simile non previsto in cui si può applicare lo script, a volte senza modifiche, o con il cambiamento di pochissime righe di codice (di solito comicianti con if cond == ...). Le modifiche possono essere sue o di altri, anche tosti.

Insomma io avevo il codice vecchio e in ogni caso non credo che potesse capitare con Linux. Ma non si può fare tutto, presto e bene… (inizio-cit.).
Vero che non c’era scritto nel manuale –anzi non c’è manuale– ma NO! se ti viene in mente un’estensione chiedi, possibilmente a chi il programma l’ha scritto. Se invece fai modifiche dillo –anche a me.
Ma –soprattutto– niente modifiche estemporanee, neanche se te le chiede teh boss dicendo che è urgente.
È come la storia della farfalla che sbatte le ali nell’Amazzonia…

Tutte cose risapute? Certo! ma continuano a capitare. Da ieri ci sono un paio di persone che hanno un’esperienza in più, anche da raccontare. Io invece non imparerò mai, ma lo racconto lo stesso qui :mrgreen:

Y combinator

cr7

Eli Bendersky ha un blog che seguo da sempre. Oggi –ahemm qualche giorno fa– posta questo: Some notes on the Y combinator. Roba che ho letto quando era già sera, non ho capito tanto (ahemmm niente, nada, zilch) e me lo sono sognato tutta la notte.
Non so se avete idea di quale possa essere la personificazione (incubosa) di Y? Credo di no. E non chiedetemi di raccontarvela; diciamo che al mattino vi sentite un po’ come ci si sente in questi tempi pre-referendum 😦

Eli rockz (al solito) e parte con il link alla Wiki, ottimo (al solito).
Ma a me, per la mia storia & sono vecchio (auto-cit.) viene subito una domanda, forse solo mia, forse peregrina, forse senza senso, forse troppo ovvia, ma in ogni caso questa: “serve? quando si usa?“. Notare che non metto in discussione che si possa usare, mica mi metto contro Haskell Curry, Eli, et al. (notare che per l’occasione uso anche l’Oxford comma, solo questa volta).

Eli svolge in dettaglio tutta la lezione. Come si usa in questi casi parte con il Lisp, cioè un dialetto della famiglia, uno che ultimamente è di moda (perso non conosco nessuno che lo usi, ma non conosco neanche chi usi un Lisp).

Clojure (ecco, sa quello) è immediato (quasi) per il lisper anche niubbo (come me). Ad esempio la funzione factorial-rec di Eli:

(defn factorial-rec [n]
  (if (zero? n)
    1
    (* n (factorial-rec (- n 1)))))

in Racket diventa:

(define [factorial n]
    (if (zero? n)
        1
        (* n (factorial (- n 1)))))

C’è solo una una keyword che cambia nome (defn invece di define) e una parentesi spostata!
Ricordo che () e [] sono intercambiabili; anche se nessun racketeer scriverebbe come qui sopra.
Passo-passo si arriva a Y combinator – a tool for making anonymous functions recursive.

Ah! capito (forse): è come lambda, una variante (super) di lambda 😀
Se sono impreciso è perché fin lì ci arrivo, porta passiensa (auto-cit.).

Non ho riprodotto l’esempio con Clojure (dovrei reinstallarlo) ma ecco, con Racket:

(define Y
  ((lambda (f)
     (f f))
   (lambda (z)
     (lambda (f)
       (f (lambda (x) (((z z) f) x)))))))

(define factorial
  (Y (lambda (recursive-factorial)
       (lambda (x)
         (if (<= x 0)
             1
             (* x (recursive-factorial (- x 1))))))))

(print (factorial 1000))

1000 può sembrare grosso ma no, nope:

y0

Ho eseguito 5 run ottenendo per real 236, 196, 203, 250 e 194 ms.

Confronto con la versione ricorsiva liscia, questa:

y1

Il tempo di esecuzione è simile al precedente (e troppo piccolo per essere significativo), comunque ho rilevato 209, 207, 242, 191 e 200 ms.

Reindirizzando l’output su file posso poi confrontare i risultati

y2

ovviamente 😀

Ma Eli va avanti: The Y combinator in Python.
Finally, just to show that the Y combinator isn’t something unique to the Lisp family of languages, here’s a Python implementation:

ycombinator = lambda func: \
    (lambda self: func(lambda n: (self(self))(n)))(
        lambda self: func(lambda n: (self(self))(n)))

factorial = lambda recurse: \
    lambda n: \
        1 if n == 0 else n * recurse(n - 1)

print((ycombinator(factorial)) (400))

y3

Velocissimo per n non troppo grande altrimenti

y4

che finisce con

y5

Sì dice sempre Eli It’s even possible to create the Y combinator in C++. Static typing makes it somewhat less elegant than in the more dynamic languages, but C++14’s generic lambdas help a lot.

Resta la mia domanda iniziale, serve?
Ci ho googlato su un po’, trovato un esempio in JavaScript, suggerimento If you’re ready for a long read, Mike Vanier has a great explanation collegato a un riassunto commendevole: long story short, it allows you to implement recursion in a language that doesn’t necessarily support it natively. Tutto qui.

Trovata anche la risposta (l’altra non quella universale (42)): How are Y combinators used in practice?
They are not used in practice. They are nice theorical tool to provide recursion in a language without built-in recursion. Because all practical programming languages supports recursion natively, there is no use for Y.
Già detto che Quora rockz! :grin:?

OK, caso chiuso (?) 😀

:mrgreen:

Gilles, Julia & me – programmazione e blog

info-processing

L’amico Gilles mi chiede via Twitter “Come si programma in python il gioco degli scacchi?” completo di link a un tool per giocarci distanza. Cosa che una volta si faceva via mail, snail-mail, quella con il francobollo e tanta pazienza.

Risposta sintetica per Gilles (e tutti quanti): non lo so, non ne ho idea ma credo che in letteratura si possa trovare, per esempio

cbb
anche se arXiv può portare fuori strada

abb

precisare, p.es.: arxiv chess big blue.

Ma ci sono altre due osservazioni che vorrei aggiungere, anche per non dare l’impressione –non corretta– di non saper cosa dire:

  • Python vuole la maiuscola, capisco che Twitter non permette di correggere i cinguettii, la fretta e quant’altro, ma per la precisione;
  • non è questione di Python o meno; il linguaggio di programmazione è un mezzo, serve per implementare l’algoritmo (è da tanto che volevo usare anch’io questo termine, finalmente l’occasione!).

Certo non tutti i linguaggi sono usuali, come non tutti gli attrezzi servono per fare le stesse cose: se uno ha un martello… (inizio-cit.).
Ah! ‘spetta: neanche tutti i martelli sono uguali, vedi Marx (citation needed ma non trovata) e qui.

Sull’algoritmo. In questi giorni personalmente tutto andava storto. Non solo Trump ma anche le specifiche di uno script (troppo semplice per chiamarlo programma) da scrivere –appunto– in Python. Quando ho detto che si poteva fare sono stato precipitoso e incoscente; dovevo leggere le specifiche con molta più cura, sottilineare, prendere appunti sulle cose da chiedere. Strada facendo mi sono perso, ne ho raccontato (e un po’ me ne vergogno) qui.
Anche perché non è vero che tutti i linguaggi di programmazione sono uguali, alcuni sono più uguali degli altri (cit.).

julia

Ma basta con questa roba. C’è anche altro. Julia Evans della quale ho postato qui sta andando avanti.
Anche se non credo basti per diventare un über-nerd come lei il suo nuovo blog e i suoi tweets aiutano. Vedi qui, qui e qui.
La lovvo e se non fossi timido che lo direi (diressi?).

:mrgreen: