Agli ordini

Agli ordini

Esercizio di apprendimento

Introduzione

Format: le basi

Common Lisp ha un concetto, The Printer, che comprende tutte le funzioni per scrivere rappresentazioni testuali dei dati Lisp. Una di queste funzioni è format, che permette allo sviluppatore di formattare i dati come preferisce.

Le capacità di format e del Printer di Lisp in generale sono un argomento molto ampio: qui descriveremo le basi dell'uso di format.

La funzione FORMAT

La funzione format accetta almeno due argomenti: uno stream su cui stampare e una stringa di controllo che definisce cosa e come va stampato.

Gli stream sono un concetto a sé e verranno descritti altrove. Per ora, tutto ciò che serve sapere è che la stampa avviene sullo stream e che per questo argomento ci sono due valori speciali: t e nil. t significa stampare sullo standard output (in realtà lo stream a cui è legata la variabile *standard-output*), mentre nil significa creare una stringa e restituirla.

Nota che format restituisce sempre nil, tranne nel secondo caso, in cui nil è specificato come stream. È un modo comune per fare una semplice interpolazione o costruzione di stringhe.

(format nil "hello world") ; => "hello world"
(format t "hello world")   ; => NIL (but "hello world" is printed to standard output)

Le direttive di formato

La stringa di controllo può contenere «direttive di formato», che danno istruzioni a format su cosa stampare e su come interpretare gli altri parametri passati a format. In un certo senso, la stringa di controllo è un programma che format interpreterà ed eseguirà. Tutte le direttive iniziano con ~ e sono seguite da un carattere (ad esempio ~A, ~D, ~&). Maiuscole e minuscole non fanno differenza.

La maggior parte delle direttive di formato si limita a interpolare nell'output un argomento di format. In questo caso si dice che l'argomento viene «consumato». Alcune direttive non consumano argomenti, altre ne consumano più di uno. Una direttiva permette persino di saltare da un punto all'altro della lista di argomenti o di saltare degli argomenti.

Formattazione di base

Una direttiva di formato molto generica è ~A. Stampa una versione dei dati «leggibile da un essere umano».

(format nil "Value = ~a" 10)                ; => "10"
(format nil "hello ~a" "world")             ; => "hello world"
(format nil "The list is: ~A" (list 1 2 3)) ; => "The list is: (1 2 3)"

Un'altra direttiva di formato utile è ~S. Stampa una versione dei dati «leggibile da una macchina». Può essere molto utile se vuoi riuscire a interpretare l'output prodotto come dati Lisp. Per molte cose apparirà identica a ~A, ma nota che, per esempio, nel caso delle stringhe l'output includerà le virgolette (con escape quando è incluso in un'altra stringa), così che il valore possa essere riletto come parametro di tipo stringa.

(format nil "~s" 10)            ; => "10"
(format nil "~s" "hello world") ; => "\"hello world\""
(format nil "~s" (list 1 2 3))  ; => "(1 2 3)"

Altre due direttive molto utili sono ~% e ~&. La prima produce un carattere di nuova riga, mentre la seconda produce una «riga nuova». La differenza è che ~% produce sempre una nuova riga, mentre ~& ne produce una solo se non ci si trova già all'inizio di una riga. Nessuna delle due consuma un argomento.

(format nil "~%new~%lines") ; => "
                                  new
                                  lines"

(format nil "~&new~&lines"  ; => "new
                                  lines"

Infine ~~ è una direttiva semplice che produce un ~ letterale.

Istruzioni

Come quasi chiunque abbia un lavoro, Layla l'aliena Lisp a volte ha bisogno di preparare dei report per comunicare informazioni agli altri. Ti chiede se puoi aiutarla a formattare i dati che ha per questi report.

1. Formattare i valori trimestrali

La prima cosa di cui Layla ha bisogno è una funzione: format-quarter-value che prende due parametri: il trimestre di calendario e il valore, e li formatta per un report. Dovrebbe restituire una stringa.

(format-quarter-value "last" 3.14) ; => "The value last quarter: 3.14"
(format-quarter-value "this" 0) ; => "The value this quarter: 0"

2. Il report dei due trimestri

Layla ti ringrazia per la funzione format-quarter-value e dice che sarà molto utile nella prossima funzione che serve.

Il prossimo report deve mostrare il trimestre e il valore di 2 trimestri stampati su due righe.

Inoltre l'output deve andare sullo stream fornito come primo argomento.

Per esempio: (format-two-quarters t "last" 3.14 "this" 0) produrrà quanto segue sullo standard output:


The value last quarter: 3.14
The value this quarter: 0

Nota le righe vuote che lo circondano.

3. Leggibile da umani e alieni Lisp

Layla si è dimenticata di dirti che agli alieni Lisp piace vedere i valori in un modo leggibile come dati Lisp. Quindi serve una nuova funzione che possa essere letta come dati Lisp (di nuovo sullo stream specificato):

(format-two-quarters-for-reading nil "last" 3.14 "this" 0) ; =>

"(\"The value last quarter: 3.14\" \"The value this quarter: 0\")"
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Common Lisp Exercism

Vuoi iniziare Agli ordini?

Iscriviti a Exercism per imparare e padroneggiare Common Lisp con 27 concetti92 esercizi e il mentoring di persone reali, tutto gratis.