Lisp – loop per cinture nere – 2

j10Seguendo Peter continuo da qui.

Cicli con collezioni e packages

Le clausole for per iterare le liste sono molto più semplici di quelle aritmetiche. Supportano solo due frasi proposizionali: in e on.

Una frase nella forma:

for var in list-form

cicla var per tutti gli elementi della lista prodotta dalla valutazione di list-form:

l2

A volte ci può essere anche la clausola by per percorrere la lista al contrario. Il default è cdr ma si può usare qualunque funzione che torni una lista. Per esempio per prenderne uno sì e uno no:

l3

L’on è usato per ciclare var sulle cons cells che formano una lista:

l4

E questa frase può avere anche un by:

l5

Ciclare su un vettore (comprese stringhe e bit vectors) è come per le liste solo che si usa across invece di in:

l6

Iterare un hash table o un package è leggermente più complicato perché questi hanno differenti set di valori che possiamo voler saltare –chiavi o valori nella table e simboli nel package. Entrambi i tipi di queste iterazioni seguono lo stesso schema, la cui forma base è:

(loop for var being the things in hash-or-package ...)

Dove per le tables i possibili valori per things sono hash-keys e hash-values che causano var a assumere i successivi valori delle keys o dei valori della hash table. La form hash-or-package è valutata una sola volta per produrre un valore che dev’essere una hash table.

Per iterare in un package things può essere symbols, present-symbols e external-symbols che causano var a collegarsi a ogni simbolo accessibile nel package (cioè internato o importato nel package) o in ogni simbolo che è stato esportato dal package. La form hash-or-package è valutata per produrre il nome del package che è visto come nella find-package o un oggetto package. Sono disponibili anche sinonimi per parti della clausola. al posto di the si può usare each; si può usare of invece di in; e things può essere al singolare.

Infine, siccome si vogliono spesso sia le keys che i valori della hash table queste clausole supportano un uso di subclausole alla fine della clausola per la hash:

(loop for k being the hash-keys in h using (hash-value v) ...)
(loop for v being the hash-values in h using (hash-key k) ...)

Entrambe questi cicli collegano k a ogni key nella hash e v al corrispondente valore. Notare che il primo elemento della subclausola using dev’essere nella singular form (Don’t ask me why loop’s authors chickened out on the no-parentheses style for the using subclause. (cit.)).

Iterazioni equals-then

Se nessuna delle altre clausole per for funziona per quel che devi fare allora devi prendere il controllo completo con la clausola equals-then. Questa è simile a quella del do ma in modo più algolico. Il modello è:

(loop for var = initial-value-form [ then step-form ] ...)

dove var è il nome della variabile del ciclo. Il suo valore iniziale è ottenuto valutando initial-value-form una sola volta prima della prima iterazione. In ogni iterazione susseguente step-from è valutato e il suo valore diventa il valore di var. Senza la parte then della clausola initial-value-form è rivalutato per ogni iterazione per fornire un nuovo valore. Notare che questo è diverso da una clausola do senza step.

step-form può riferirsi a altre variabili di cicli, incluse variabili create da altre clausole susseguenti nel ciclo. Per esempio:

l7

(matto 👿 imho).
Notare che ogni clausola è valutata nell’ordine in cui compare. Quindi nel ciclo precedente nella seconda iterazione x è settato al valore di y prima che y cambi (cioè 1) ma y è poi settato al al suo vecchio valore (ancora 1) e al nuovo valore di y (qui ho cambiato, forse typo).
Se l’ordine delle clausole è invertito il risultato cambia:

l8

Spesso si vuole il passo per forms per variabili multiple valutate prima di ognuna che le nuove variabili assuma il suo nuovo valore, come il do gestisce il passo per le sue variabili. In questo caso si possono unire clausole for multiple sostituendole tutte tranne la prima con and. Esempio:

l9

Nota personale: io la frase precedente l’avrei semplificata di molto 👿

Variabili locali

Mentre le variabili principali richieste dentro a un loop sono usualmente dichiarate implicitamente nella clausola for a volte ne servono di ausiliarie che si dichiarano con with:

with var [ = value-form ]

Il nome var diventa il nome di una variabile locale che cessa di esistere quando il loop finisce. Se il with contiene una parte = value-form la variabile viene inizializzata prima della prima iterazione a quel valore.

with multipli possono apparire in un loop: ogni clausola è valutata indipendentemente nell’ordine in cui appare e il valore assegnato prima di procedere con la clausola successiva, permettendo a variabili seguenti di dipendere da valori per variabili già dichiarate. Variabili mutualmente indipendenti possono essere dichiarate con un with con clausole and tra le dichiarazioni.

Destrutturazione di variabili

loop può destrutturare liste di valori assegnati alle variabili del ciclo. Questo consente di usare il valore di liste che altrimenti verrebbe assegnato a una variabile del ciclo, allo stesso modo di destructuring-bind ma meno elaborato. In sostanza si può rimpiazzare ogni variabile del ciclo in una clausola for o with con un albero di simboli e il valore della lista che dev’essere assegnata a una semplice variabile può invece essere destrutturata in variabili nominate dai simboli dell’albero (capito niente, nada, zilch!). Esempio semplice:

l10

L’albero può contenere anche liste puntate nel qual caso il nome dopo il punto agisce come parametro &rest, venendo collegato a ogni elemento rimanente della lista. Questo torna particolarmente utile con cicli for/on siccome il valore è sempre una lista. Esempio, questo ciclo per scrivere una lista delimitata da virgole:

l11

può essere riscritto così:

l12

Se si vuole ignorare un valore nella lista destrutturata si può usare nil al posto del nome della variabile:

l13

Se la lista destrutturata contiene più variabili dei valori presenti le variabili extra sono settate a nil, rendendo tutte le variabili come se fossero parametri &optional. Cosa diversa dai parametri &key.

Continua :mrgreen:

Posta un commento o usa questo indirizzo per il trackback.

Trackback

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: