Subroutines 2 : implementazione

Vediamo adesso come realizzare ed utilizzare le subroutine in Perl. A tal fine ci serviranno i concetti introdotti nella lezione precedente, in particolare per quanto riguarda la funzione shift. Iniziamo a considerare la seguente subroutine:

# Subroutine di controllo (verifica che la variabile sia definita)
sub checkVar {
	my $arg = shift ;
	return 1 	if (defined $arg && length $arg > 0) ;
	return 0 ;
}

che si occupa semplicemente di controllare che la variabile passata come argomento sia definita e non nulla. Per invocare la subroutine possiamo scrivere:

if (checkVar($arg))	 etc... etc..

Notiamo l'uso della funzione shift per leggere la variabile di default che contiene la lista degli argomenti. In altre parole, omettendo l'argomento della funzione shift è come se scrivessimo shift(@_). Gli argomenti passati alla funzione (nell'esempio qui sopra la variabile $arg) sono infatti "trasmessi" dall'interprete Perl proprio attraverso l'array di sistema @_ (vedi qui).

Nota: per motivi didattici la funzione checkVar è stata implementata mostrando un esempio di utilizzo delle keyword defined e length. In particolare la keyword defined serve a verificare che una variabile sia definita in modo da evitare un warning durante la compilazione. Un modo più semplice di risolvere il problema potrebbe essere quello di disabilitare i warnings di questo tipo, scrivendo (all'inizio del file):

no warnings 'uninitialized';

Detto questo proviamo a vedere come implementare altre subroutines, ad esempio:

# Subroutine di stampa di una riga (aggiunge carattere NEW LINE)
sub println {
	my $arg = shift ;
	print $arg if (checkVar($arg)) ;
	print "\n" ;
}

Questa subroutine stampa una linea su STDOUT, seguita dal carattere new line (CR o LF a seconda del sistema operativo). In particolare notiamo che la subroutine invoca quella scritta prima, cioè la checkVar(): questa è solitamente una buona pratica perché permette di centralizzare in modo unico le diverse logiche e/o operazioni, semplificando la manutenzione del codice e favorendo il riuso dello stesso.

Una versione leggermente più complessa di questa subroutine potrebbe essere:

# Subroutine di stampa di più righe (stampa n righe uguali)
sub printLines {
	my ($arg, $num, @others) = @_ ;
	if (checkVar(@others)) {
		println("Too many arguments: @others") ;
		return ;
	}
	elsif (checkVar($num))	{	
		println($arg) for 1..$num ;
	} else {
		println($arg) ;
	}
}

che introduce le seguenti features:

  • Possibilità di stampare più volte il contenuto della variabile $arg, passando un secondo parametro ($num) che indica il numero di linee da stampare
  • Controllo sul numero di parametri passati in ingresso
  • Utilizzo della keyword return per interrompere l'esecuzione
  • Riferimenti alle subroutine sviluppate in precedenza, per migliorare manutenzione e incentivare il riutilizzo del codice

Per testare il corretto funzionamento delle nostre subroutine proviamo ad eseguire:

# Esempi di utilizzo delle diverse subroutine
println() ;
println("Esempio di utilizzo della subroutine (println)") ;
printLines("Altro esempio di subroutine (printLines)") ;
printLines("Stampa multipla (printLines)", 5) ;
printLines("Invocazione sbagliata (printLines)", 5, 123) ;
println() ;

Che produce come risultato

Esempio di utilizzo della subroutine (println)
Altro esempio di subroutine (printLines)
Stampa multipla (printLines)
Stampa multipla (printLines)
Stampa multipla (printLines)
Stampa multipla (printLines)
Stampa multipla (printLines)
Too many arguments: 123

Ovviamente possiamo usare la keyword return anche per ritornare un valore come esito della subroutine, come nelle normali funzioni o procedure. Trattandosi di una funzionalità comune a quasi tutti i linguaggi di programmazione lasciamo al lettore il compito di sperimentare l'utilizzo della keyword return.



Home Pagina 14 di 15