Esercizio: r-cat quasi rifare cat – 1

206363_v1Una prova per vedere se ho capito qualcosa –e cosa– di tutta questa lunga serie di post su Racket. Un esempio semplicissimo, una versione semplificata del comando cat. Niente di particolare ma c’è la lettura di file, la scrittura (su terminale ma non cambia), gli argomenti sulla linea di comando, e altro ancora.
Siccome sono all’inizio (niubbo praticamente) scriverò anche cose scontate (così non me le dimentico). OK, inizio.

Il file di testo che verrà utilizzato è txt, questo:

file txt
che contiene
qualche linea
di testo

dopo una vuota.

La forma più semplice è probabilmente rc0.rkt:

#lang racket

;; leggo in blocco e scrivo riga per riga
(define my-file "txt")
(for ([line (file->lines my-file)])
  (displayln line))

r0

OK, funziona! DrRacket è una IDE eccezionale, indispensabile. Trova gli errori, aggiusta l’indentazione, indica dove sono usate le variabili (sì, qualcuna ci vuole) e tante altre cose ancora. In questo caso l’esecuzione è automatica (click su Run) altrimenti c’è la finestra d’interazione.

Una nota (per me): la funzione file->lines non è contenuta in racket/base quindi il #lang non è quello usuale, neanche per la versione da terminale (rc0t.rkt):

#!/usr/bin/racket
#lang racket

;; leggo  in blocco e scrivo riga per riga
(define my-file "txt")
(for ([line (file->lines my-file)])
  (displayln line))

r1

Rispetto alla versione precedente è solo stata inserita la shebang. Si può lanciare sia con racket sia abilitandola (OK, elementare ma sono niubbo :loll:)

Questo script è banale ma c’è una cosa che non mi piace: non so se sono solo io ma queste istruzioni sparse non mi vanno; molto meglio raggrupparle in una o più funzioni, in fondo questa è (dovrebbe essere) programmazione funzionale. La definizione di my-file rientra nella funzione? Ci ho pensato su un po’ e ho deciso di no: se lo script fosse più complesso probabilmente verrebbe usata in più funzioni e allora… Ovvio che va deciso caso per caso ma per far pratica la tengo globale. Nel terminale sono necessari un paio di aggiustamenti (rc1t.rkt):

#!/usr/bin/racket
#lang racket

;; leggo in blocco e scrivo riga per riga
(define my-file "txt")
(define (main)
  (for ([line (file->lines my-file)])
    (displayln line)))

;; eseguo
(main)    

Se il file non è troppo grosso (e tutti sono sempre nella categoria dei piccoli) conviene leggerlo in blocco, tutto in una volta, come fatto negli script precedenti. Leggere una riga per volta è leggermente più complesso (rc1s.rkt):

#lang racket

;; leggo e scrivo riga per riga
(define my-file "txt")

(define (read-next-line-iter file)
       (let ((line (read-line file)))
         (unless (eof-object? line)
           (displayln line)
           (read-next-line-iter file))))

(define (main)
  (call-with-input-file my-file read-next-line-iter))

(main)

OK, andiamo oltre (rc2.rkt):

#lang racket

#|
leggo in blocco e scrivo riga per riga
|#

(define my-file "txt")

(define (main)
  (define nr 0)
  (define lines (file->lines my-file))
    (for ([line lines])
      (set! nr (+ nr 1))
      (displayln (format "~a ~a" nr line))))

r3Qualche cosa nuova: numero delle righe nell’output e commento su più righe. La versione per terminale ha in più solo la shebang e la chiamata a main, non la riporto.
In questa versione vengono usate funzioni nuove, p.es. format. Diventa importante l’help attraverso la REPL:

r4

r5

Poi quando non si trovano le cose, come faccio a leggere il file? vero che ne ho scritto in passato ma la via più veloce a volte (quando si finisce la pazienza è Stack Overflow (non so se faccio bene a confessarlo ma sì :roll:). Poi, ripensandoci il nome ha una sua logica: da file a string ma… Uh! si trova qui. Poi si usa la REPL.

Pausa 😀 ci sono ancora cose da fare, per esempio non tutti i file di testo si chiamano txt.

Uh! ‘na nota: non comincio più i titoli con “Racket -” tranne quando copio seguo la guida.
: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: