A volte non è come sembra – il blog

lisplogo_warning_256Ecco una cosa che devo proprio dire anche se probabilmente interessa solo a me e E e A e pochi altri.
Intanto, una domanda preliminare: perché c’è chi non vuole mai comparire sui social-cosi, nemmeno con il solo nome? Per esempio ci sono tanti Alberto e/o Adriano e/o Andrea (indovinate quale dei tre). Invece di E così molto poche, da noi poi rarissimissime, forse è unica, chissà se…
Ah: naturalmente se non v’interessa non leggetelo, nèh! :wink:

Le puntate domenicali della telenovela Visto nel Web sono facili da montare: basta registrare titolo e URL di quello che leggo in un file di testo e il più è fatto. Poi la domenica mattina, subito dopo un paio di caffè, processo il file con uno script Python (che ultimamente è diventato diversamente bello e se fosse di un altro direi che non si programma così, per niente) che mi compila l’HTML. Basta aggiungere le immagini LOLlose (?), verificare e postare. Sono i post più visti di gran lunga; quelli che portano la media giornaliera a 200 visite (circa). Dividento per 1.6-1.7 si ha il numero di visitatori (grazie, vi amo), alcuni dei quali arrivano da molto lontano (grazie anche a voi, vi amo ancora di più, anche quelli che sono nostri finiti là; gli altri come fanno con l’italiano?).

Ci sono post evergreen, vecchi, vecchissimi, che continuano a essere visti; pochi accessi alla settimana ma sempre loro. Sono quelli che riguardano C/C++, anche molto specifici, quelli di glipari (ovvio), quelli sulle interfacce grafiche GTK e affini per Python. Anche tutto Python piace.
Poi ci sono quelli su altri linguaggi, p.es. Ruby. E ci sono richieste per Lua, Scala, Julia, … tutta roba che non conosco bene o non conosco affatto e non ho tempo di vedere.
Un po’ di tempo fa ho parlato di Gnuplot, pare interesi solo me. Come pure il Fortran, oggi si usa Matlab. Ecco qui c’è un’altra cosa che non mi va: è proprietario, non freeware. Ne esiste un clone FOSS, Octave (e altri affini), ma non è completo (o comunque non usato). Inoltre per queste cose (ma non ne faccio più) mi viene chiesto di tenerle riservate, non ha senso, imho, ma è così.
E poi ci sono episodi burst, ogni tanto ne salta fuori uno, ultimamente JavaScript. Non ci devo più cascare.

Invece avendo tempo mi piacerebbe seguire Rust, forse ancora troppo giovane e Go già maturo. Un mio conoscente si è convertito, mi aveva anche promesso mezza paginetta sull’argomento, chissà… :wink:

Poi ci sarebbe quella che è la moda del momento: la programmazione funzionale. Forse, chissà… Prevedere il futuro, dice Niels…
Invece no a HTML, e dintorni, no a Android e iCosi, no a Delphi, C# e roba che non frequento (o non frequento più).

Ma tutta questa tirata per un paio di motivi, esasperati ieri da una discussione di quelle senza capo ne coda ma che poi non ti lasciano dormire.

Online ci sono blog e siti fatti molto bene che trattano quasi tutto quanto detto sopra. Quelli che conosco e quelli che man-mano scopro li elenco in Blogroll, lo trovate qui, nella colonna a sinistra, anzi è in testa.

Se ne avete da suggerire ditemelo. Chi finisce in quell’elenco poi non sarà –salvo eccezioni– più riportato nella telenovela domenicale.
Ma è in Blogroll che dovete vedere se cercate tutorial e/o affini.
Anzi ne ho qualcuno scoperto proprio ora (OK, qualcuno suggeritemi dai miei 00x, con x = 7 ma anche no). Non li ho ancora esaminai a fondo, forse finiranno in Bloroll, per adesso ecco:

The New Stack non ho ancora capito bene cosa sia ma ha parecchia roba dentro.

Proprio ora @Donearm segnala I Do Not Know C. La home del sito è piena di cose da vedere, chissà se anche questa finirà in Blogroll?

Ma il motivo vero del post è un altro, adesso ve lo devo proprio dire: mi piace tantissimissimo-anzi-di-più-moltissimissimo-di-più il Lisp, Common Lisp. È roba vecchia (avrebbe bisogno di una revisione, qualcuno l’ha anche proposta). Interessa solo me, ci sono post che hanno avuto 2-4 visite (magari inconsapevoli). Ma rassegnatevi, continuo. Caso mai non leggete :mrgreen:
Anzi adesso torno a lispare. Ecco :grin:

Lisp – un DB semplice – 4

thw6
Continuo da qui, sempre seguendo l’ottimo Peter Seibel.
Avendo creato le funzioni select e where si può procedere all’aggiornamento del DB, facendo come in SQL. Salta fuori che la funzione update è solo un’applicazione di cose già viste, usare una funzione selettore per scegliere i record da aggiornare e usare keywords per specificare i valori da cambiare.

La cosa nuova è l’uso della funzione mapcar:

(mapcar function_list+)
Return list of return values of function successively in-
voked with corresponding arguments, either cars or cdrs,
respectively, from each list.

dice Bert Burgemeister.

Ma prima devo ricaricare nella REPL quello che mi serve dalla volta precedente, che pal.

db0

OK, pare che sia tutto a posto. Il file s-prec contiene il riassunto di quanto definito precedentemente, con le righe vuote per separare le diverse forme e funzioni ormai è di 30 righe (avendo tolto il superfluo); non lo allego.

db1

Notare l’uso di setf in una form complessa come (get row :title). Rimandando a poi i dettagli su setf per ora vediamo solo che è un operatore di assegnamento che può essere impiegato per assegnare diversi pezzi, non solo variabili.
Nota di Peter: getf e setf hanno nomi simili ma nessuna relazione speciale.
Nota mia: proprio come le parole get e set. OOPS! lì la relazione stretta c’è eccome!
Per adesso notare che dopo (setf (getf row :title) title) la plist referenziata da row avrà il valore della variabile title che segue il property name :title. Con questa funzione –update– si può decidere di promuovere le Dixie Chicks, dandogli il voto di 11:

db2

Si può facilmente aggiungere una funzione per cancellare record (rows) nel DB:

db3

La funzione remove-if è il complemento di remove-if-not; ritorna una lista con tutti gli elementi che non soddisfano il predicato rimossi. Come per remove-if-not non cambia la lista passatagli e per salvare i cambiamenti in *db* usiamo delete-rows. Qui viene usato il nome delete-rows perché c’è già la funzione delete nel Common Lisp; si potrebbe gestire il tutto, se sapessimo già usare i packages. E, dice ancora Peter: non è come sembra, la memoria non usata viene riciclata efficientemente.

Adesso tutto il codice per inserire, selezionare, aggiornare e cancellare record nonché un’interfaccia REPL per aggiungere nuovi record e visualizzare il contenuto del DB è poco più di 50 righe. Qui Peter fa come parecchi prof tosti che ho conosciuto (il mio relatore G.M. Bo, il boss dell’istituto (allora i dipartimenti si chiamavano così) F. Levi et al.), riporto, senza tradurre:

peter seibel

A friend of mine was once interviewing an engineer for a programming job and asked him a typical interview question: how do you know when a function or method is too big? Well, said the candidate, I don’t like any method to be bigger than my head. You mean you can’t keep all the details in your head? No, I mean I put my head up against my monitor, and the code shouldn’t be bigger than my head.

OK, tornado al DB c’è ancora una cosa da aggiungere: la duplicazione del codice. Cosa che facendola rende anche il codice più flessibile. La duplicazione di cui vogliamo trattare è in where, dove sono presenti righe come questa:

(if title (equal (getf cd :title) title) t)

Per adesso non è un problema ma se il codice cresce e vuoi cambiare qualcosa devi andarle a cercare e sostituire tutte. E poi se stai aggiornando devi testare per tutte le linee, insomma, sarebbe molto meglio invece di:

(select (where :title "Give Us a Break" :ripped t))

avere qualcosa come:

(select
#'(lambda (cd)
(and (equal (getf cd :title) "Give Us a Break")
(equal (getf cd :ripped) t))))

Notare che questa funzione anonima è differente da quelle che where avrebbe ritornato; non si tenta di salvare la chiamata a where ma di provvedere una funzione selettore più efficiente. Questa funzione anonima riguarda solo i campi che interessano in quel momento e non l’intero record quindi non fa niente più di quello richiesto.

Adesso verrebbe naturale andare a aggiustare il codice tutto dove compare where; cosa lunga e rischiosa se il codice è lungo. Se ce n’è abbastanza si potrebbe anche pensare di scrivere un preprocessore…
La caratteristica che rende questo decisamente facile è il sistema delle macro. Ci ricordiamo che sono una cosa completamente diversa da quelle robe con lo stesso nome del C e C++, vero? Quando il preprocessore del C/C++ fa la sostituzione testuale delle macro praticamente ignora tutto del C/C++. Una macro Lisp è essenzialmente in generatore di codice che viene eseguito automaticamente per te dal compilatore (e questo meccanismo funziona anche nella versione interpretata; si parla del compilatore solo per ragioni di chiarezza). Quando un’espressione contiene una chiamata a una macro, invece di valutarne gli argomenti e passarli alla funzione il compilatore Lisp passa gli argomenti, senza valutarli, al codice della macro, che ritorna al Lisp l’espressione che viene poi valutata invece della chiamata originale alla macro.

Partiamo con un esempio semplice. Introduco la funzione reverse che prende una lista e restituisce una nuova lista con i componenti invertiti. Per esempio (reverse '(1 2 3)) ritorna (3 2 1). Adesso creiamo la macro:

db4

Sintatticamente cambia solo defmacro al posto di defun. Tuttavia la macro ha un effetto completamente diverso, esempio:

db5

Vediamo cos’è successo. Quando la REPL inizia a valutare backwards la riconosce come macro e quindi lascia l’espressione ("hello, world" t format) non valutata –ottimo perché non sarebbe corretta per il Lisp– e passa questa lista al codice di backwards che passa la lista a reverse che ritorna (format t "hello, world"). backwards quindi passa questo valore alla REPL che la valuta al posto dell’espressione originale.

La macro backwards quindi definisce un nuovo linguaggio che è quasi come il Lisp, solo all’incontrario, al quale puoi passare un’espressione Lisp a rovescio. Nella versione compilata questo nuovo linguaggio è efficiente come il Lisp normale perché tutto il codice delle macro viene eseguito al tempo della compilazione. In altri termini viene generato lo stesso codice sia che si scriva (backwards ("hello, world" t format)) che (format t "hello, world").

Vediamo ora come questo può servire per il nostro codice duplicato in where. Possiamo scrivere una macro che genera esattamente il codice richiesto per ogni particolare chiamata a where. Al solito l’approccio migliore è procedere bottom-up. Nella funzione selettore manualmente ottimizzata si ha un espressione della seguente forma per ogni campo riferito nella chiamata originale a where:

(equal (getf cd field) value)

Scriviamo una funzione che, dato il nome di un campo e un valore, ritorni questa espressione. Siccome un’espressione è solo una lista si potrebbe pensare di scrivere qualcosa come:

(defun make-comparison-expr (field value)    ; wrong <----
(list equal (list getf cd field) value))

Tuttavia, c’è un trucco qui: quando il Lisp vede un nome semplice come field o value che non sia il primo elemento di una lista lo prende per una variabile e ne cerca il valore. Questo è OK per field e value, è quel che si vuole. Ma vengono trattati allo stesso modo equal, getf e cd, che non è quel che si vuole. Si può tuttavia bloccare la valutazione con  un apice prima del nome. Così se si può scrivere:

db6

che posso testare:

db7

OK, ma c’è un modo ancora migliore. Vogliamo un modo di scrivere un espressione che sia per la maggior parte non valutata ma in cui alcune parti siano valutate. Che cu fortuna: questo meccanismo c’è, con la back-quote, questa `.

tasti

Parentesi personale che poi capace che me ne dimentico: sulla tastiera italiana si ottiene con AltGr+, vedi figura.

Tornando a noi:

db8

Quindi usando una back-quote si può riscrivere make-comparision-expr così:

db9

Adesso guardando alla funzione selettore ottimizzata manualmente si nota che il corpo della funzione consiste in un espressione di comparazione per ogni coppia di campo/valore, raggruppate con un and. Considerate per un attimo di mettere insieme tutti gli argomenti in una singola lista da passare  alla macro where. Quello che serve è una funzione che prenda questa coppia di campo/valore e raccolga i risultati  della chiamata a make-comparison-expr per ogni coppia. Uhmmm… trafficando  un po si ottiene con la meravigliosa e potente macro loop.

db10

Riserviamo per il momento una disamina approfondita a loop. Per adesso ci basta osservare che loop fa esattamente quel che ci serve: cicla finché ci sono campi nella lista estraendone due per volta, passandoli a make-comparison-expr e raccogliendone i risultati alla fine del ciclo. La macro pop fa l’inverso di push, usata per aggiungere record a *db*.
Adesso basta impacchettare la lista ritornata da make-comparison-list in un and e una funzione anonima, cosa che si può fare nella macro where stessa. Usando una back-quote per creare un template che riempia interpolando il valore di make-comparisons-list è banale (dice Peter :roll:):

db11

Questa macro usa una variante di , vale a dire ,@ prima della chiamata a make-comparisons-list. ,@ raggruppa i valori delle espressioni seguenti che deve valutare come una lista date nella lista.
Si può valutare la differenza tra , e ,@ con le seguenti espressioni:

db12

,@ può essere usata anche nel mezzo di una lista:

db13

L’altra caratteristica importante della macro where è l’uso di &rest nella lista degli argomenti. Come &key &rest modifica il modo con cui gli argomenti vengono esaminati. Con un &rest nella lista dei parametri una funzione o una macro può prendere un numero arbitrario di parametri che sono raggruppati dentro una singola lista che diventa il valore della variabile il cui nome segue &rest. Così se si chiama where in questo modo:

(where :title "Give Us a Break" :ripped t)

la variabile clauses conterrà la lista:

(:title "Give Us a Break" :ripped t)

Questa è passata a make-comparisons-list che ritorna una lista di espressioni comparate. Si può vedere il codice generato per una chiamata a where usando la funzione macroexpand-1. Passando a macroexpand-1 una form rappresentante una chiamata a una macro, viene chiamata la macro con gli argomenti appropriati e ne ritorna l’espansione. Così verifichiamo la precedente chiamata a where:

db14

Sembra buona, provo con il caso reale:

db15

Funziona. E con queste due funzioni d’aiuto la macro where è ora una riga più corta e più generale e non più legata a un campo specifico del CD.

È successa una cosa interessante: si è rimossa la duplicazione e si è reso il codice più efficiente e generale al tempo stesso. Cosa che capita sovente con una macro ben scelta. Ha senso perché una macro è solo un altro modo per creare astrazioni, astrazione al livello sintattico e le astrazioni sono per definizione modi più concisi per esprimere le generalità sottostanti.
Adesso il solo codice del mini-DB per i CD e i loro campi è nelle funzioni make-cd, prompt-for-cd e add-cd. La macro where funziona per ogni DB basato su plist.

Però questo è ben lontano dall’essere un DB completo. Si può pensare a parecchie funzioni da aggiungere, quali il supporto di più tabelle e query più elaborate. Cosa che Peter promette per il cap. 27, oggi siamo alla fine del 3; volendo rilanciare il video del post precedente.

Lascio a Peter la conclusione:

The point of this chapter was to give you a quick introduction to just a handful of Lisp’s features and show how they’re used to write code that’s a bit more interesting than “hello, world.” In the next chapter we’ll begin a more systematic overview of Lisp.

Personalmente ci devo pensare su un po’, assimilare… Pausa :grin:

J una nuova utility vecchia di 30+ anni

Avvertenza: questo post può avere effetti collaterali per chi è allergico al terminale. Avvisati, nèh! :mrgreen:

keep-calm-and-bin-bash-7Quando io ero piccolo il mio ‘puter era il PR1ME 550, un mini.
Adesso dovrei raccontarvi che il mini era un armadio quattro due stagioni, aveva 512 KB di RAM, un disco da 80 MB e –OK, altri tempi.
Anche il sistema operativo era diverso Primos, derivato da Pick, derivato da Multics (forse, la Wiki non lo dice). Ma era già nuovo, mica c’erano più le schede perforate che al Poli gli studenti continuavano a usare.

Allora qualcuno di noi (Ugo? Piergiorgio?) aveva semplificato il comando ATTACH, l’equivalente Linux di cd. Ogni comando era abbreviabile, dovevi digitarne solo la parte iniziale, nel nostro caso A; ma poi dovevi –dopo il nome della UFD (directory)– digitare la modalità d’accesso, p.es. per accedere a LAB sottodirectory di JUHAN directory di MFD, vale a dire  Master File Directory potevi fare:

A JUHAN>LAB 1 2

o anche in due tempi:

A JUHAN 1 2
A *>LAB 1 2

Non vi dico cosa sono quei numeri –è un segreto– oppure me lo sono dimenticato, è passato un po’ di tempo.
Allora qualcuno dei nostri aveva creato J. Dapprima era molto semplice, poi si era evoluto, potenza del CPL (Command Process language) un linguaggio di scripting che suppliva la non programmabilità della shell (che non si chiamava shell ma COMMAND, la richiamavi con R (run)). OK, per andare alla directory— UFD LAB digitavi J L. Ah! di solito scrivevi tutto maiuscolo ma era indifferente.
Io il comando j l’ho rifatto subito per DOS quando sono passato ai PC IBM compatibili, quelli di Micro$oft. Non ero invece riuscito a farlo con Unix, non avevo abbastanza tempo e non m’era venuto subito, anzi… :mrgreen:
joelPoi ho provato a rifarlo con Linux, ne ho anche parlato in passato, qui sul blog. Ma mi hanno detto di autojump che funziona benissimo. Bravo Joel Schaerer (joelthelion).
Quindi niente? No, fino a questa mattina. Poi l’ho rifatto. È molto facile, semplicissimo. OK, l’ho copiato.
È andata che l’altro giorno ho googlato per non ricordo esattamente cosa ma c’erano di mezzo bash, function e non so cos’altro (non riesco a ritrovarlo). E ho scoperto le funzioni che si possono definire per bash, una cosa che avevo sempre saltato o trascurato o –OK, colpa mia.

Siccome j è già usato (a volte) per j, ovvio (no, non quello di joelthelion, quell’altro da matematici) il nuovo J l’ho chiamato J (d’ho!) maiuscolo; come sul Pr1me.

È tutto qui:

function J {
    case $1 in
        j) cd ~/lab/APPs/J/ ;;
        sca) cd ~/Scaricati ;;
        T) cd ~/tmp ;;
        -e) gedit ~/.Jd ;;
        -l) cat ~/.Jd ;;
        -u) source ~/.Jd ;;
        *) cd ~/lab ;;
    esac
}

J
È il file ~/.Jd. Per attivarlo automaticamente basta aggiungere a ~/.bashrc la riga:

. ~/.Jd

Che ne dite?
Ah! ‘na roba: non ditelo a quelli che sono convinti che su Linux si lavora solo con il terminale, sapete com’è :roll:

Visto nel Web – 172

È stata la settimana della Net Neutrality; ho già rendicontato ma qui in fondo ci metto gli aggiornamenti. Chissà se… :grin: Intanto ecco cos’altro ho visto nel Web.

Angelica Atondo

Angelica Atondo

5 ways Ubuntu is better than Windows
::: I am Programmer

Le sei norme del Book Hacking
::: Mariano Tomatis

Preparing for ECMAScript 6
::: Web Design Weekly

RT @loffio: Scorpacciata di medioevo, offre La Nazione
::: nonleggerlo

How Walking With Smartphones May Have Changed Pedestrian Etiquette
::: Slashdot

The Most Diabolical Python Antipattern
::: Real Python

icsmall

Google Webfonts, The Spy Inside?
::: The FontFeed

Alan Turing, fra storia e stereotipi
vecchio ma l’avevo perso :roll:
::: Oggi Scienza

Un Pulitzer, un Oscar… che altro ci vuole per capire che quanto rivelato da Snowden è stato davvero importante per tutti?
::: carolafrediani ::: The Intercept

Linux Kernel Switching To Linux v4.0, Coming With Many New Addons
::: Slashdot

Sull’Open Source e Linux: è adatto a tutti e a tutto?
::: Marco’s Box

nq150213

Lenovo and the Superfish Scam
1. Don’t ever buy a Lenovo computer. Never, ever, ever.
2. If you have a Lenovo computer already, get rid of it.
::: Good Math/Bad Math

AVIDAC, Argonne National Laboratory’s first digital computer, January 1953
::: oldpicsarchive

golang merge dev.cc (a91c2e0) into master
::: golang ::: Google+

Cultura digitale. Hiroshi Ishii: “I bit saranno i nuovi atomi”
::: Messaggero Veneto

Il PRG di #Palermo con gli #opendata
::: giowile

B-CiJfqIgAAmgzn

Hacking Python AST: checking methods declaration
::: Julien Danjou

Software Patents Are Increasingly Coming Under Fire In Court
::: TechCrunch

Google Teams Up With 3 Wireless Carriers To Combat Apple Pay
::: Slashdot

La velocità con cui cambia il mondo
::: Giuseppe Granieri

Transcript: NSA Director Mike Rogers vs. Yahoo! on Encryption Back Doors
::: Just Security

paura

1 in 3 Laptops fail over 3 years: Netbooks fail 20% more than laptops
::: SquareTrade

Hacklab X – Anno 2, Edizione Speciale 1
::: Hacklab Cosenza

Google and blogs: “Shit.”
::: Marco.org

Shannon, McCarthy, Fredkin, and Weizenbaum 1966
::: LispWorld

I’m no longer convinced that adding to scipy should be our goal
::: jakevdp

B-JsDqBCAAA7_Fw

We would be at 50% unemployment
::: SwiftOnSecurity

I use @libreoffice on both Linux and M$ Windoze and love it
::: WolfieSmiffed

Common Lisp in the 21st Century
::: CL21

At the heart of Hailo: a Golang geoindex library
::: The Hailo

How to Use KDE Plasma Desktop Like a Pro
::: :::Linux.com

B-WkMZBCIAAtf6M

The Case Against E-readers — Why Digital Natives Prefer Reading On Paper
::: Slashdot

Optimizing Python in the Real World: NumPy, Numba, and the NUFFT
jake lo metto nel Blogroll
::: Pythonic Perambulations ::: jakevdp

Intro.js: Step-by-step guide for your projects
::: DevPen

Microsoft introduces ASP.NET 5, runs on Windows, Mac and Linux
d’ho! :roll:
::: WinBeta

AMD’s next laptop processor is mostly about battery life
::: Engadget

I'm Programmer

I’m Programmer

Opening keynote: The 5 stages of learning Go (with examples), Francesc Campoy
::: Sourcegraph

miniMAL – A Lisp implemented in < 1 KB of JavaScript with macros, TCO, interop and exception handling
::: kanaka

La #ScuolaDigitale Gestisce gli account via fax
::: MarcoAlici

One in four students uses social media to contact university staff
::: THE

Patterns for composable concurrent pipelines in Go
::: Gopher Academy

Arteide

Arteide

Il Kindle del 1922
::: Zen-Funk Panda

Web Starter Kit for Angular Dart – Samples
::: Web Starter Kit

Facebook’s Colonies
::: Slashdot

The Programmers Who Want To Get Rid of Software Estimates
::: Slashdot

Who Wins The Battle of The Disrupted Tech Giants: HP Or IBM?
::: TechCrunch

Italia Unita per la Scienza

Programmando si impara: da Samsung un progetto per il coding nelle scuole
::: il Sole 24 Ore

10 Trucchi per Win 7-8
::: OpenFreeMan

Linux su chiavetta: YUMI e Linux Live USB Creator a confronto
::: OpenFreeMan

Firefox Hello
::: OpenFreeMan

lucen

Obiettivi raggiunti
::: Gli Amici di Lubit

La censura chiude la pagina Facebook Dimissioni e tutti a casa
::: Piovegovernolad

Most requests to censor tweets
::: conradhackett

The countries with the fastest and slowest broadband speeds
::: thei100

Il vostro sito è compatibile con i dispositivi mobili? Chiedetelo gratis a Google
per entrambi i blog ottengo “Fantastico. Questa pagina è ottimizzata per i dispositivi mobili.” sono bravo, assay :wink:
::: Il Disinformatico

10262031_10205272139117228_8060265277333154496_n

Tim Cook Says Apple Watch Could Replace Your Car Keys, And That’s Just The Start
::: TechCrunch

Do programmers have any specific superstitions?
::: dbgrandi

Si les langages de programmation étaient des taxis
::: CommitStrip

Chinese internet giants purge 60,000 accounts for inappropriate usernames
::: Engadget

1959474_825329697502769_3109623278055914106_n

Russians Take to Social Media to Mourn Boris Nemtsov
::: The Moscow Times

Check Out Google’s Insane Plans for a New Headquarters
::: Bloomberg

Anche il secondo CoderDojo è stato bellissimo
::: dcavedon

@gasparripdl

Net Neutrality: Triumph of the Ruling Class
::: Beautiful Anarchy

Net neutrality. E ora tocca all’Europa
::: Luca De Biase

FCC Adopts Net-Neutrality Rule Backed by Obama for Internet
::: Bloomberg

Internet: si scrive ‘net neutrality’, si traduce ‘libertà’
::: Il Fatto Quotidiano

Neutralità della rete, una vittoria dell’attivismo e dei cittadini
::: Wired

So, whatever happened to net neutrality in Europe?
::: EDRi

CARLO-GIOVANARDI

Non una parola sullo storico voto sulla #netneutrality dal presidente-del-digitale-e-dell’innovazione
::: fabiochiusi

#NetNeutrality victory! Grumpy Cat flies over @Comcast HQ
::: ScottMSanders

Here’s how far we’ve come with net neutrality
::: Engadget

F.C.C. Moves to Free Up Community Broadband Services
::: Bits

salvini

Net Neutrality

ew
Trovate tutto qui: Join the Battle for Net Neutrality. Adesso stanno festeggiando, ci sono anche i fuochi artificiali, ma metti che aggiornano –mica finisce qui, anzi Ce n’est qu’un debut (auto-cit.)– allora cito:

Washington insiders said it couldn’t be done. But the public got loud in protest, the FCC gave in, and we won strong, Title II net neutrality rules. Now Comcast is furious. They want to destroy our victory with their massive power in Congress. You won net neutrality. Now, are you ready to defend it?

e ancora:

Cable companies lobbied so hard. But we, the public, sent the FCC a message so loud they couldn’t ignore us. The FCC voted to preserve Net Neutrality, with strong Title II rules that prohibit ISPs like Comcast from slowing down and breaking the sites and apps you love.

Inoltre c’è Twitter –come farei senza Twitter? (nuova auto-cit.).

Partial victory: FCC votes for bright line rules protecting #netneutrality, but we’re still worried about the general conduct rule.

“Tonight’s the night for a party and tomorrow we go back to work.” Our job ain’t done.

Net neutrality”No one, whether government or corporate, should control the open and free access to the Internet.” –Wheeler #fcclive

Our products would be A LOT less fun if it wasn’t for the Internet. THIS is an historic day. #NetNeutrality #FCC

no, Verizon non l’ha presa bene. #NetNeutrality

One year ago, every person I know who understands the FCC or internet policy considered net neutrality dead. But the people were heard.

It’s a better day for the internet! Go Go Gadget Net Neutrality. 👍

27net-web

Tom Wheeler, chairman of the F.C.C., with two fellow commissioners, Mignon Clyburn, left, and Jessica Rosenworcel, right, during an open hearing on Thursday ahead of a vote on net neutrality. Credit Mark Wilson/Getty Images

OK, una rassegna come quelle di Visto nel Web, adoro fare lo storico, o almeno il cronista, o almeno m’illudo di essere tale. Ma voglio farlo :grin:

FCC Adopts Strong, Sustainable Rules to Protect the Open Internet

FCC Chairman Tom Wheeler: This Is How We Will Ensure Net Neutrality

Obama, AT&T, Verizon, Netflix and more react to the FCC’s historic net neutrality vote

How activism won real net neutrality

What Net Neutrality Means for You, the Internet User

FCC approves net neutrality rules, reclassifies broadband as a utility

Net Neutrality: FCC Passes New Rules for Internet

F.C.C. Approves Net Neutrality Rules, Classifying Broadband Internet Service as a Utility

FCC votes in favor of net neutrality, reclassifies ISPs

Now The Internet Belongs To Us — And To Politics

How 14 major news outlets explain net neutrality

La FCC ha approvato le nuove regole sulla Net Neutrality

Usa, arriva il sì alla Net neutrality: “Internet uguale per tutti”

Obama salva la neutralità di Internet

OK, a Verizon non è piaciuta neanche un po’ guarda qua: Verizon issues furious response to FCC, in Morse code, dated 1934.

Lisp – un DB semplice – 3

trudbolDov’ero rimasto? Ah sì! qui: Lisp – un DB semplice – 2, al punto in cui ho salvato il mio DB nel file di testo ~/lab/lisp/my-cds.db.

Avendo chiuso la REPL lo ricarico. Però devo anche ridefinire *db* la variabile globale che contiene il DB:

db0

E adesso posso ricaricarlo:

db1

Adesso ho un modo per caricare tutto il DB, ma spesso è utile visualizzare sono qualche record. Potrei usare grep o sed o AWK o altro ma non sarebbe lispico. Quello che voglio è qualcosa di simile a:

(select :artist "Dixie Chicks")

che mi ritorna solo i record delle Dixie Chicks.
Uh! le Pollastrelle del Sud, sì, qui il loro sito, ma sono fuori tema, scancello :wink:

Uso la funzione remove-if-not che prende un predicato (funzione che ritorna un valore booleano) e una lista e ritorna nil per falso e qualsiasi altra cosa per vero.

Per esempio se voglio estrarre i pari da una lista di numeri posso scrivere

db2

In questo caso il predicato è la funzione evenp (finisce con p) che ritorna vero se il numero è pari. La notazione (buffa dice Peter) #' è la scorciatoia per “dammi la funzione con quel nome”. Senza #' il Lisp avrebbe considerato evenp come il nome di una variabile e cercato quella invece della funzione.

Alla remove-if-not si può passare anche una funzione anonima; supponiamo che non ci sia evenp l’espressione precedente può essere riscritta così:

db3

In questo caso la funzione anonima è:

(lambda (x) (= 0 (mod x 2)))

che testa se il numero modulo 2 è 0, cioè pari; per estrarre i dispari si userebbe:

(lambda (x) (= 1 (mod x 2))).

Notare che lambda non è il nome di una funzione ma l’indicatore che sto definendo una funzione anonima. Peraltro l’espressione di lambda è simile a quella di defun: manca il nome della funzione ma c’è la lista dei parametri seguita dal corpo della funzione.

Tornando al DB per estrarre i record relativi alle Dixie Chicks serve una funzione che ritorni true per i record in cui il campo :artist è Dixie Chicks. Avendo costruito il DB con plist possiamo usare getf con l’espressione (getf cd :artist) e per estrarre quelli buoni usare equal: (equal (getf cd :artist) "Dixie Chicks"). Impacchettiamo tutto in un’espressione lambda che passiamo alla remove-if-not:

db4

OK, generalizzando per un qualunque artista si può scrivere:

db5

Ma potrei voler selezionare per gli altri campi e creare select-by-title, select-by-rating, select-by-title-and-artist e via dicendo. Sempre usando la stessa funzione anonima. Invece si può creare usa funzione di selezione più generale che prende una funzione come un argomento.

db6

Cos’è successo a #'? Ecco, in questo caso non voglio che remove-if-not usi la funzione selector-fn ma una funzione anonima che viene passata attraverso la variabile selector-fn. In ogni caso #' ritorna nella call a select:

db7

ma è brutta, fortunatamente si può ricorrere a una funzione anonima:

db8

questa è una funzione che ritorna una funzione e che si riferisce a una variabile che sembra non esistere dopo che artist-selector ritorna. Questa è chiamata closure perché “closes over” (chiude sulla) la variabile, vedremo prossimamente.
Sembra una cosa strana (d’ho!) ma funziona proprio come dovrebbe: se chiamo artist-selector con “Dixie Chicks” come argomento ottengo una funzione anonima che ritorna i CD in cui :artist è “Dixie Chicks” e ottengo un altra funzione chiamandola con “Lyle Lovett”. Posso così scrivere:

db80

Adesso basterebbero solo un pakko di funzioni per generare i selettori. Ma non voglio creare select-by-title, select-by-rating e così via, perché sembrerebbe Basic o PHP :grin:
Sarebbe bello creare una funzione selettore general-purpose che genera la funzione selettore in funzione degli argomenti passati.
OK, si può. ma prima un rapidissimo corso di una caratteristica del Lisp, i keyword parameters.

Finora nelle funzioni scritte si è specificato una semplice lista di parametri, collegati ai corrispondenti argomenti nella chiamata alla funzione. per esempio la seguente funzione:

(defun foo (a b c) (list a b c))

ha 3 parametri –a, b e c– e deve essere chiamata con 3 argomenti. Ma a volte si vuole scrivere una funzione che può essere chiamata con un numero variabile di argomenti. I keyword paramters sono un modo per far ciò. La nostra funzione che li usa diventa:

(defun foo (&key a b c) (list a b c))

L’unica differenza è &key all’inizio della lista degli argomenti. Ma il risultato è diverso:

db9

(Nota: OK, sì, c’è ormai da parecchie parti, anche nel Basic).

Come si vede dagli esempi i valori delle variabili a, b e c sono collegati ai valori che seguono le corrispondenti keyword. Per le keyword non presenti la variabile è posta uguale a nil. Ma se si vuole si può fare in modo che il valore della variabile per la keyword mancante abbia un valore diverso, di default. Si ottiene questo sostituendo la lista dei parametri con una lista consistente  nel nome del parametro, un valore di default e un altro parametro chiamato parametro supplied-p. Il parametro supplied-p viene posto vero o falso a seconda di come viene fatta la chiamata:

db10

Il generatore generale di selector-function, una roba da SQL, è una funzione che ha 4 keyword parameters corrispondenti ai campi del nostro DB di CD e genera una funzione selettore che seleziona i CD che soddisfano tutti i valori dati in where. Per esempio si potrà scrivere:

(select (where :artist "Dixie Chicks"))

o, anche:

(select (where :rating 10 :ripped nil))

La funzione è questa:

db11

Questa funzione (where) ritorna una funzione anonima che ritorna l’and per tutti i campi per ogni cd in cui la condizione è soddisfatta. Quindi la funzione selettore ritorna t solo se tutti gli argomenti passati sono soddisfatti.

Parentesi (di Peter): if in Lisp è una forma che ritorna qualcosa, è simile all’espressione C some_var = some_boolean ? value1 : value2; mentre è diverso da some_var = if (some_boolean) value1; else value2; perché nel C (e affini) if è un’istruzione (statement) e non un ‘espressione.

notare che per la keyword parameter ripped si devono passare 3 parametri perché si occorre sapere se la chiamata con :ripped nil significhi “seleziona i CD in cui il campo ripped è nil” oppure, quando non specificato stia per “non m’interessa il campo ripped per il CD”.

Pausa? La strada, dice Peter, è ancora lunga, mi sembra di aver accumulato tanto oggi. :roll:
E poi tutta questa musica, non so voi ma a me fa venire in mente questo:

Julien Neel –Trudbol– sì che saprebbe lispare come si deve :grin:

Sul calcolo di base elevato esponente

1425797_10201940668950614_1418135656_nIeri sulla pagina Figli di Archimede, legittimi e… in adozione (su Facebook, non riesco a linkarla) Cristiano Armellini si chiede:

C’è un modo per definire una potenza con base negativa ed esponete razionale ? esempio (-2)^(7/5) … se provate a eseguire il calcolo con diversi software o ottenete un errore o un numero complesso, probabilmente il computer lo vede come e^(7/5 ln(-2)) che è complesso perché c’è il log di un numero negativo….ma questo passaggio non si potrebbe applicare per gli esponenti interi es (-2)^3 = -8 che non è complesso. Tuttavia (-2)^(1/3) è ben definito come la radice cubica di -2.

Verifico, intanto la versione C (tp.c):

#include <stdio.h>
#include <math.h>

int main () {
    double b = 2.0,
           e = 7.0 / 3.0;
    printf("%lf ^ %lf = %lf\n", b, e, pow(b, e));
    b *= -1;
    printf("%lf ^ %lf = %lf\n", b, e, pow(b, e));
    return(0);
}

COK con la base positiva, nan se negativa.

Vediamo Python, io sono un convinto Python-evangelista:

py

Stesso comportamento del C, anche se il messaggio d’errore è chiaro. Ovviamente questo è reso possibile nella modalità interattiva. Ah! sì, sono anche REPL-evangelista :wink:

Quando devo fare calcoli al volo io sono affezionato a calc:

calc

Ottimo, invece dell’errore ottengo un risultato complesso. Da esaminare più approfonditamente :wink:

Anticamente, prima di calc c’era bc:

bc

Se non ho sbagliato qualcosa no, non ci siamo. Ma essendo scale il numero di cifre decimali credo che il messaggio sia da intendere come “esponente non intero”. Uno sguardo al manuale chiarisce:

expr ^ expr
The result of the expression is the value of the first raised to
the second.  The second expression must be an integer.  (If  the
second  expression is not an integer, a warning is generated and
the expression is truncated to get an integer value.)  The scale
of  the  result  is  scale  if the exponent is negative.  If the
exponent is positive the scale of the result is the  minimum  of
the  scale  of the first expression times the value of the expo‐
nent and the maximum of scale and the scale of the first expres‐
sion.    (e.g.   scale(a^b)   =   min(scale(a)*b,   max(  scale,
scale(a))).)  It should be noted that expr^0 will always  return
the value of 1.

Ultimamente sono alle prese con il Lisp, Common Lisp (cit?):

cl

Stessi risultati di calc, bravo SBCL :grin:

Ma c’è un’altra versione molto sexy di Lisp ottima per script veloci, newLISP:

nl

Rivela che sotto c’è il C (o C++). Notare che i numeri per noi italiani hanno la virgola e newLISP lo sa (è peraltro possibile normalizzare, anzi se si usano certi moduli è indispensabile).
Esiste (prima o poi ne parlerò) un altro sapore di Lisp piccolo e performante: Picolisp. Ma tratta nativamente solo gli interi (sì, devo proprio parlarne, prima o poi).

Un’ultima osservazione: quando ottenendo un numero complesso (calc e CL) c’è un ulteriore risultato calcolabile, la norma (o modulo (o valore assoluto)):

norma

Ecco, come previsto :grin:

Infine, confessione: confesso di non aver chiara la questione del segno della base per calcoli con il ‘puter. Roba da matematti :grin:

Dov’è che l’ho già vista?

Sapete quando capita che un’immagine ti sembra di averla già vista, come oggi :roll:

Non ricordo dove ma mi ricorda qualcosa, adesso vi racconto.
ma prima una premessa: anche su questo blog uno non è che non può ogni tanto fare qualcosa di diverso, LOLlos, per esempio. Poi –davvero– non lo farò più, anzi smetto subito appena posto questa pagina ho promesso ‘na roba a Luigi Bit3Lux, quello di Lubit.

Tutto è partito da qui: Microsoft developing People Sense app for finding friends on Windows Phone. Non che m’interessi particolarmente –anzi– ma c’è quest’immagine:
mssa
Mi sembra –come dicevo– già vista, non nuova. Chissà dove… ah! sì, ecco:

Logo_Ubuntufuochino, non proprio quella ma qualcosa di simile. Adesso Google permette di cercare immagini simili a una che droppi nel campo di ricerca, chissà…

No, non ho trovato quello che cercavo, anche se questa qua sotto mi sembra interessante:
Ubuntu-7-04-Well-Done-2
Ok, non ci sono per nessuno devo fare quella roba là per Luigi :mrgreen:

Visto nel Web – 171

Raccolto troppi link; da oggi in poi non vi dico più di quelli che ci spiano, non voglio sembrare ripetitivo. Tanto dovreste saperlo ormai. Ci sono altre cose, nuove –almeno per me. Intanto ecco cosa ho visto nel Web.

1795531_850326901680936_8139530035684005225_n
Should We Really Try To Teach Everyone To Code?
::: Slashdot

The fascinating truth behind all those ‘great firewall of China’ headlines
::: the Guardian

WebSockets the UNIX way
Full duplex messaging between web browsers and servers
::: websocketd

Bank Hackers Steal Millions Via Malware
::: Slashdot

nosebook
a nose plugin for finding and running IPython 3 notebooks as nose tests
::: bollwyvl

West Point and Marines Launch Open Cyber Conflict Journal
::: Slashdot

B9jSWd9IMAAokLH

Why Apple is the most successful company in history
applevangelist, probabilmente
::: ComputerWorld

Best Resources to Learn JavaScript
::: Programming Concepts

The Ten Commandments of Egoless Programming
vecchio ma OK
::: Coding Horror

Floppy disks are like Jesus
::: Twitter

Quante Arduino esistono? Il pasticcio (e le cause) tra Ivrea, Stati Uniti e Svizzera
::: il Sole 24 Ore

fb11

Nim Programming Language Gaining Traction
::: Slashdot

Bonafè: “una efficace lotta al terrorismo non può prescindere da un controllo della Rete”
::: Twitter ::: Twitter

#python tip
::: Twitter

How Big Telecom Tried To Kill Net Neutrality Before It Was Even a Concept
::: Slashdot

Don’t Be Google
::: TechCrunch

10942585_902824066429298_2452585728710717865_n

7 Useful Tricks for Mastering a New Programming Language
::: makeuseof

Raspberry Pi 2 Model B: una prima recensione
::: Marco’s Box

Playing with continued fractions and Khinchin’s constant
::: The Endeavour

The FAA’s new rules for flying drones in the US won’t allow Amazon to deliver packages by air
::: The Next Web

Russia: arrestato Alexei Navalny, il blogger anti Putin
::: RaiNews24

B9yf0GuCIAEB99S

Social media: A network boost
Nature continua a darmi ragione: usate Twitter :wink:
::: Nature

Map of the entire Internet in 1969
::: Twitter

Every research paper PDF I’ve ever read
::: Twitter

How “Omnipotent” Hackers Tied To NSA Hid For 14 Years and Were Found At Last
::: Slashdot

Spionaggio USA, Kaspersky Lab svela il legame con Western Digital, Seagate, Toshiba e altri produttori di hard disk
::: Downloadblog

I'm Programmer

The Software Revolution
::: Slashdot

PC-BSD: Set For Serious Growth?
::: Slashdot

Google and blogs: “Shit.”
::: Marco.org

Sony’s augmented reality glasses are now available for pre-order at $840
::: The Next Web

La signora Brigitte e i marchi registrati
::: manteblog

Sir Duck

Spanish politicians turn to social media in pursuit of lost voters
::: the Guardian

Una directory di link diretti per eliminare il tuo account dai siti web
::: Just Delete Me

When Chess Players Blunder
::: Slashdot

The Face Detection Algorithm Set To Revolutionise Image Search
::: Technology Review

KiCad software gets the CERN treatment
::: CERN

B95MGONIYAAPd70

Si vendono sempre più workstation, soprattutto nel settore mobile
::: Businessmagazine

Python usage survey 2014
quale versione 2.x o 3.x?
::: Randal S. Olson

Raspberry PI cross building native (C/C++) graphical applications from Windows
::: biicode

Raspberry Pi has sold 5 million of its DIY-friendly computers
::: Engadget ::: Twitter

The Unbearable Lightness of Tweeting
::: The Atlantic

B98qw5zIMAAIS10

Apple Patents Head-Mounted iPhone
::: Slashdot

Patent Troll Wins $15.7M From Samsung By Claiming To Own Bluetooth
::: Slashdot

Dalle ceneri di CrunchBang nasce il progetto CrunchBang ++
::: TUXJournal

Bruce Schneier: “Ecco come i nostri dati vengono usati per
::: Agenda digitale

Using find and xargs
::: Connor Johnson

crate

HTTP/2 Finalized
::: Slashdot

Online C/C++ Learning resources
::: I am Programmer

Torvalds: “People Who Start Writing Kernel Code Get Hired Really Quickly”
::: Slashdot

Government, Military and Private Sector Fighting Over Next-Gen Cyber-Warriors
::: Slashdot

10930846_740718159368748_1179351474173352830_n

Java Vs. Node.js: Epic Battle For Dev Mindshare
::: Slashdot

After 30 Years of the Free Software Foundation, Where Do We Stand?
::: Slashdot

Google: FBI’s Plan To Expand Hacking Power a “Monumental” Constitutional Threat
::: Slashdot

Microsoft’s Trojan Horse To Undermine Android
::: Forbes ::: The New York Times

Jamie Oliver’s Website Serving Malware
::: Slashdot

10984064_1568319710076716_5865770027974355365_n

Jony Ive resterà alla Apple? Una storia del New Yorker
::: Luca De Biase

Cutegram 2: chattare con Telegram da Linux non è mai stato così bello!
::: TUXJournal

Lenovo PCs ship with man-in-the-middle adware that breaks HTTPS connections
::: Ars Technica

Linux, il codice è aziendale
::: Punto Informatico

Pisa: Things on internet cerca di rendere facile mettere le cose online
prossimamente; per intanto hanno un bel sito web
::: Luca De Biase

10942737_223838871119989_1324085001054035569_n

My heart fills with joy
::: Twitter

full Circle Magazine
da parecchio (troppo) tempo non ne parlo
::: Full Circle Magazine

Material Design icons by Google
::: google

Gadgets That Spy On Us: Way More Than TVs
::: Slashdot

OLPC’s modular hybrid laptop could last schools for years
::: Engadget

5hNJsIW

Microsoft’s First Azure Hosted Service Is Powered By Linux
::: Slashdot

How NSA Spies Stole the Keys To the Encryption Castle
::: Slashdot

Il Nuovo Planet LUG
::: Italian Linux Society

AT&T Patents System To “Fast-Lane” File-Sharing Traffic
::: Slashdot

Does Open Data Have a Dark Side?
::: Slashdot

1-2

U.S. To Scale Back Its Role In Internet Governance
::: TechCrunch

About the Computer History Museum’s IBM 1401 Machines
::: Computer History Museum

Codemotion Tech Meetup 2015 Roma – appunti sparsi, video e slide
::: Grab the Blaster

A brief history of Swift language performance
::: Twitter

Gist command line interface
‘gist’ is a command line interface for working with github gists. It provides several methods for inspecting a users gists, and the ability to easily create them
::: github

10987720_10203903814023550_6990519308215938081_n

How Machine Learning Ate Microsoft
::: Slashdot

Redirecting all kinds of stdout in Python
mah… :roll:
::: Eli Bendersky

How to easily remove Superfish adware from your Lenovo laptop
::: Twitter

Stay ahead of the pack with Freescale S32 automotive processors. Coming soon.
::: Twitter

As well as SIM card maker Gemalto, GCHQ hacked into phone companies to delete charges for malicious SMSes from bills
::: Twitter

wbNEUTRONS

LOD Hackathon: rendiamo semantici i dati della PA piemontese
::: giuseppefutia

Who’s writing Linux today? Capitalists
::: ZDNet

Homo pluralis: una lettura in breve
::: Luca De Biase

Superfish CA + Komodia vulnerability test (updated!)
::: PyTux

Why Sony Should Ditch Everything But the PlayStation
::: Slashdot

1797948_865091800195814_1990040150755472671_n

The Robots That Will Put Coders Out of Work
::: Slashdot

Facebook: bloccare gli inviti ad applicazioni ed eventi (selettivamente)
::: Gioxx

Your Mobile Privacy is Under Threat Because of US and UK Spies
::: Global Voices Advocacy

eBook made simple
Editor di contenuti digitali per l’editoria, la formazione e la didattica
::: ePub Editor

Italian Formula One Grand Prix

Is Twitter giving in to Turkish censorship?
::: Al-Monitor

Open Data (e Open Source) – La narrazione viene dopo
::: Grab the Blaster

Addictive anti social side to Facebook
::: Twitter

B9b3C6qIgAEf7oL

Lisp – un DB semplice – 2

thw5Continuo dal post precedente, seguendo Peter Seibel nella costruzione di un DB semplice.
E salta fuori subito un problema: sono niubbo (ancora) e uso la REPL; sono anche discolo e non uso SLIME, trovo più semplice la mia.
Adesso dovrei richiamare tutti i simboli (variabili, funzioni) creati nel corso del post precedente; si può fare, sono nella history ma c’è una scorciatoia: load.
Ho copiato in un file di testo chiamato s-prec (sì, non mi è venuto in mente niente di meglio) quello che dovrei richiamare, eccolo:

;; contiene il codice per continuare il DB

(defun make-cd (title artist rating ripped)
  (list :title title :artist artist :rating rating :ripped ripped))

(defvar *db* nil)

(defun add-record (cd) (push cd *db*))

(add-record (make-cd "Roses" "Kathy Mattea" 7 t))
(add-record (make-cd "Fly" "Dixie Chicks" 8 t))
(add-record (make-cd "Home" "Dixie Chicks" 9 t))

(defun dump-db ()
  (format t "~{~{~a:~10t~a~%~}~%~}" *db*))

db0

OK, funziona. Il T restituito da load dovrebbe essere sufficiente per indicare che tutto ha funzionato come previsto ma posso verificarlo con length. Qui ho fatto qualche prova e mi sono un po’ perso (sono ancora niubbo, lo so).
Volevo creare una funzione che mi restituisca il numero di elementi di una lista ma non sono ancora abbastanza addentro ai misteri del Lisp, qualcosa simile a questo:

db1

ye” è il piemontese di “c’è“, il suffisso “-p” è conforme alla convenzione dei predicati (funzioni booleane); non sono riuscito a gestire il caso in cui passo un parametro non esistente.: sono ancora niubbo, ma ci sto lavorando :roll:

OK, sto divagando, torno al DB, ripartendo da dove ero arrivato.
la funzione add-record funziona bene ma è rozza, sarebbe bello se ci fosse un prompt a cui rispondere, così:

db2

Si usa, al solito format, senza ~% nella stringa di formattazione in modo da restare sulla stessa riga del prompt; force-output è necessario (in alcune implementazioni) per assicurarsi che la stringa sia emessa senza attendere un aa-capo. Si può allora leggere una linea di testo con la funzione read-line che pone il risultato nella variabile globale predefinita *query-io* (ricordi gli *, vero?).
Si può quindi combinare make-cd con prompt-read per creare una funzione che crea un nuovo record dai dati che prende in risposta alle richieste:

db3

Quasi OK; prompt-read ritorna una stringa che non è quel che si vuole per i valori previsti per Rating (numerico) e Ripped (booleano). Un metodo spiccio (quick and dirty) è di usare parse-integer, così:

(parse-integer (prompt-read "Rating"))

ma parse-integer genera un errore se la stringa immessa non è un intero. È però previsto un argomento opzionale :junk-allowed che migliora un po’ le cose:

(parse-integer (prompt-read "Rating") :junk-allowed t)

ma se all’interno della stringa non c’è un intero parse-integer ritorna nil. Per fare le cose semplici vorremmo 0 invece di nil e allora usiamo la macro or che ritorna il primo valore non nil in una serie di espressioni o nil se sono tutte nil. Quindi:

(or (parse-integer (prompt-read "Rating") :junk-allowed t) 0)

Per quanto riguarda Ripped c’è la funzione y-or-n-p:

(y-or-n-p "Ripped [y/n]: ")

che continua a chiedere finché non trova y o n (minuscole o maiuscole, sembra di essere su Windoze!).
Assemblando tutto abbiamo una versione abbastanza robusta per prompt-for-cd:

db4

il warning è OK, ma sì, si sa, dai!

Infine la funzione add-cds, un semplice loop finché diciamo di smettere:

db5

e posso aggiungere qualche cd:

db6

notare che ho anche testato per un errore (ahemmm) :lol:

Il passo successivo è quello di salvare il DB in un file:

db7

La macro with-open-file apre un file, collega lo stream a una variabile, esegue una serie di operazioni e lo chiude. Qui specifico che il file, di cui devo dare il nome, viene aperto in scrittura con :direction :output e che posso sovrascriverlo con :if-exists :supersede.
Una volta aperto scrivo con (print *db* out); diversamente da format, print scrive in modo da poter rileggere i dati dal Lisp reader. Per sicurezza si usa la macro with-standard-io-syntax, non si sa mai :wink:
Forse sono discolo ma per il nome del file ne uso uno mio, non mi piace mettere tutto nella home.

db8

la funzione per caricare il DB da file è simile:

db9

Notare che non è necessario specificare :direction quando questa è :input.
La macro setf è l’operatore principale di assegnamento del Lisp. Assegna al suo primo argomento il risultato della valutazione del secondo.

OK, pausa :mrgreen:
E alla ripresa dovrò aggiornare il mio file s-prec: panico (quasi) :lol:

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Unisciti agli altri 83 follower