From 4f8711fda4857974817339e6f5fac62ec2de1e46 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 9 Aug 2008 15:33:18 +0000 Subject: fatto anche un po' di i/o git-svn-id: svn://luxion/repos/intro-perl@354 fcb26f47-9200-0410-b104-b98ab5b095f3 --- corso.content.tex | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 239 insertions(+), 5 deletions(-) diff --git a/corso.content.tex b/corso.content.tex index 297cf47..73c15a2 100644 --- a/corso.content.tex +++ b/corso.content.tex @@ -978,23 +978,255 @@ if (!exists $hash{a}) { \section{Subroutine} -\subsection{Definizione} +\begin{frame}\frametitle{Cos'è una subroutine?} +\begin{itemize} +\item un blocco di codice riusabile +\item un blocco di codice parametrico +\item uno strumento per organizzare il codice +\end{itemize} +\end{frame} + +\subsection{Definizione e invocazione} + +\begin{frame}[fragile]\frametitle{Definire una sub} +\begin{lstlisting} +sub saluta { + print "Ciao!\n"; +} +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]\frametitle{Invocare una sub} +\begin{lstlisting} +saluta(); +\end{lstlisting} -\subsection{Invocazione} +\begin{itemize} +\item una volta, si usava \lstinline!&saluta()!; ma oggi si +preferisce evitare \lstinline!&! +\item \lstinline!&! prima del nome è necessario se il nome è lo stesso +di una funzione interna di \Perl: non fatelo +\item \lstinline!$nome!, \lstinline!@nome!, \lstinline!%nome! +e \lstinline!&nome! sono tutti diversi +\end{itemize} +\end{frame} +%$ \subsection{Argomenti e valore di ritorno} +\begin{frame}[fragile]\frametitle{Sub con parametri} +\begin{lstlisting} +sub saluta { + print "Ciao $_[0]!\n"; +} + +saluta('Gianni'); +\end{lstlisting} %$ + +Gli argomenti passati a una subroutine vengono visti +nell'array \lstinline!@_!. +\end{frame} + +\begin{frame}[fragile]\frametitle{I parametri sono alias} +\begin{lstlisting} +sub azzera { + $_[0]=0; +} + +my $a=5; +azzera($a); +print $a; +\end{lstlisting} %$ + +Gli argomenti passati a una subroutine sono {\em +modificabili}. Stateci attenti! +\end{frame} + +\begin{frame}[fragile]\frametitle{Idioma per i parametri} +\begin{lstlisting} +sub saluta { + my ($nome)=@_; + print "Ciao $nome!\n"; +} + +saluta('Gianni'); +\end{lstlisting} + +Di solito si copiano gli argomenti in apposite variabili, per evitare +problemi, e per dare dei nomi ai parametri. +\end{frame} + +\begin{frame}[fragile]\frametitle{Valore di ritorno} +\begin{lstlisting} +sub somma { + my ($primo,$secondo)=@_; + return $primo+$secondo; +} + +print somma(5,12); +\end{lstlisting} + +\begin{itemize} +\item \lstinline!return! esce dalla subroutine, e restituisce il valore al +chiamante. +\item L'espressione a destra di \lstinline!return! viene valutata nello +stesso contesto in cui è stata invocata la subroutine. +\item \lstinline!return;! senza un'espressione +restituisce \lstinline!()! in contesto lista, e \lstinline!undef! in +contesto scalare +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Parametri variabili} +\begin{lstlisting} +sub somma_a_tutti { + my ($quanto,@numeri)=@_; + for my $numero (@numeri) { + $numero+=$quanto; + } + return @numeri; +} + +my @mesi=somma_a_tutti(30,1,-2,1,0,1,0, + 1,1,0,1,0,1); +\end{lstlisting} + +Notare che \lstinline!@numeri! si prende tutti gli argomenti dopo il +primo: se avessimo scritto \lstinline!my (@numeri,$quanto)=@_!, +\lstinline!$quanto! avrebbe sempre avuto il +valore \lstinline!undef!. +\end{frame} + \subsection{Variabili lessicali} +\begin{frame}[fragile]\frametitle{Che succede qui?} +\begin{lstlisting} +use strict;use warnings; +my $fuori=5; +sub prova { + my ($param)=@_;my $dentro=7; + return $param+$dentro+$fuori; +} +print "$param $dentro $fuori\n"; +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]\frametitle{Che succede qui?} +Eseguendo riceviamo degli errori: + +\begin{verbatim} +Global symbol "$param" requires explicit + package name at /tmp/tst.pl line 7. +Global symbol "$dentro" requires explicit + package name at /tmp/tst.pl line 7. +Execution of /tmp/tst.pl aborted due to + compilation errors. +\end{verbatim} +\end{frame} + +\begin{frame}[fragile]\frametitle{Che succede qui?} +\begin{lstlisting} +use strict;use warnings; +my $fuori=5; +sub prova { + my ($param)=@_;my $dentro=7; + return $param+$dentro+$fuori; +} +print "$param $dentro $fuori\n"; +\end{lstlisting} + +Il motivo è che \lstinline!$param! e \lstinline!$dentro! sono +dichiarate all'interno del blocco della sub \lstinline!&prova!, e non +sono visibili all'esterno. \lstinline!$fuori!, invece, è visibile sia +fuori sia dentro. %$ +\end{frame} + \section{Input/Output} \subsection{Qualche dettaglio in più} +\begin{frame}[fragile]\frametitle{Scorrere l'input} +\begin{lstlisting} +use strict;use warnings; +my $righe; +while (my $riga=<>) { + chomp($riga);print reverse($riga),"\n"; + ++$righe; +} +print "$righe\n"; +\end{lstlisting} + +\begin{itemize} +\item quel \lstinline!while! cicla su tutte le righe dell'input, +leggendone una alla volta +\item \lstinline!$righe! vale \lstinline!undef! all'inizio, ma %$ +l'operatore di incremento lo trasforma in \lstinline!0! (senza +marning) +\item \lstinline!reverse! inverte anche le stringhe +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Scorrere l'input, versione brutta} +\begin{lstlisting} +use strict;use warnings; +my $righe; +for my $riga (<>) { + chomp($riga);print reverse($riga),"\n"; + ++$righe; +} +print "$righe\n"; +\end{lstlisting} + +\begin{itemize} +\item fa quasi la stessa cosa di prima +\item ma ora carica tutto l'input in memoria +\item di solito non è una buona idea +\end{itemize} +\end{frame} + \subsection{Le magie di \texttt{<>}} -\subsection{\texttt{printf}} +\begin{frame}[fragile]\frametitle{L'operatore \texttt{<>}} +\begin{itemize}[<+->] +\item \lstinline!<>! legge una riga (o tutte) dall'input +\item cos'è l'input? +\item normalmente è lo {\em standard input} +\item ma se vengono passati dei nomi di file al +programma, \lstinline!<>! apre quei file, uno dopo l'altro +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Esempio di parametri al programma} +\begin{lstlisting} +use strict;use warnings; +my $righe; +while (my $riga=<>) { + chomp($riga);print reverse($riga),"\n"; + ++$righe; +} +print "$righe\n"; +\end{lstlisting} + +Se salviamo questo programma come \texttt{gira-file}, ed eseguiamo: + +\begin{verbatim} +./gira-file uno.txt due.txt +\end{verbatim} -\subsection{Codifiche} +vedremo le righe di \texttt{uno.txt} invertite, seguite da quelle +di \texttt{due.txt} invertite, e infine il numero complessivo di +righe. +\end{frame} + +\begin{frame}[fragile]\frametitle{Filehandle (anticipo)} +\begin{itemize} +\item se vogliamo leggere dallo standard input soltanto, possiamo +scrivere \lstinline!! +\item \lstinline!print! scrive normalmente sullo standard output +\item \lstinline!print STDERR 'qualcosa'! scrive sullo standard error +\item notare che manca la virgola! +\end{itemize} +\end{frame} \section{Espressioni regolari} @@ -1004,7 +1236,7 @@ if (!exists $hash{a}) { \subsection{Operatori più complessi} % anchors, parens, complex charclass (\p) -\subsection{Uso generale} % m, s, split, =~, options +\subsection{Uso generale} % m, s, split, =~, options, tr \section{Controllo del flusso} @@ -1028,6 +1260,8 @@ if (!exists $hash{a}) { \subsection{Leggere e scrivere file} +\subsection{Codifiche} % binmode e use utf8 e use encoding + \subsection{Test sui file} \subsection{Moduli da usare} % File::Spec, Path::Class -- cgit v1.2.3