Perl - Subroutine

Una subroutine o funzione Perl è un gruppo di istruzioni che insieme svolgono un compito. Puoi suddividere il tuo codice in subroutine separate. Il modo in cui suddividere il codice tra le diverse subroutine dipende da te, ma logicamente la divisione di solito è che ogni funzione esegue un compito specifico.

Perl utilizza i termini subroutine, metodo e funzione in modo intercambiabile.

Definisci e chiama una subroutine

La forma generale della definizione di una subroutine nel linguaggio di programmazione Perl è la seguente:

sub subroutine_name {
   body of the subroutine
}

Il modo tipico di chiamare quella subroutine Perl è il seguente:

subroutine_name( list of arguments );

Nelle versioni di Perl precedenti alla 5.0, la sintassi per chiamare le subroutine era leggermente diversa come mostrato di seguito. Questo funziona ancora nelle versioni più recenti di Perl, ma non è raccomandato poiché ignora i prototipi di subroutine.

&subroutine_name( list of arguments );

Diamo uno sguardo al seguente esempio, che definisce una semplice funzione e poi chiamiamola. Poiché Perl compila il programma prima di eseguirlo, non importa dove dichiari la tua subroutine.

#!/usr/bin/perl

# Function definition
sub Hello {
   print "Hello, World!\n";
}

# Function call
Hello();

Quando il programma sopra viene eseguito, produce il seguente risultato:

Hello, World!

Passaggio di argomenti a una subroutine

Puoi passare vari argomenti a una subroutine come fai in qualsiasi altro linguaggio di programmazione e possono essere acceduti all'interno della funzione utilizzando lo speciale array @_. Pertanto il primo argomento della funzione è in $ _ [0], il secondo in $ _ [1] e così via.

È possibile passare array e hash come argomenti come qualsiasi scalare, ma il passaggio di più di un array o hash normalmente fa perdere loro identità separate. Quindi useremo i riferimenti (spiegati nel prossimo capitolo) per passare qualsiasi array o hash.

Proviamo il seguente esempio, che prende un elenco di numeri e quindi stampa la loro media:

#!/usr/bin/perl

# Function definition
sub Average {
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_) {
      $sum += $item;
   }
   $average = $sum / $n;

   print "Average for the given numbers : $average\n";
}

# Function call
Average(10, 20, 30);

Quando il programma sopra viene eseguito, produce il seguente risultato:

Average for the given numbers : 20

Passaggio di elenchi a subroutine

Poiché la variabile @_ è un array, può essere utilizzata per fornire elenchi a una subroutine. Tuttavia, a causa del modo in cui Perl accetta e analizza elenchi e array, può essere difficile estrarre i singoli elementi da @_. Se devi passare un elenco insieme ad altri argomenti scalari, crea elenco come ultimo argomento come mostrato di seguito -

#!/usr/bin/perl

# Function definition
sub PrintList {
   my @list = @_;
   print "Given list is @list\n";
}
$a = 10;
@b = (1, 2, 3, 4);

# Function call with list parameter
PrintList($a, @b);

Quando il programma sopra viene eseguito, produce il seguente risultato:

Given list is 10 1 2 3 4

Passaggio di hash alle subroutine

Quando fornisci un hash a una subroutine oa un operatore che accetta un elenco, l'hash viene automaticamente tradotto in un elenco di coppie chiave / valore. Ad esempio:

#!/usr/bin/perl

# Function definition
sub PrintHash {
   my (%hash) = @_;

   foreach my $key ( keys %hash ) {
      my $value = $hash{$key};
      print "$key : $value\n";
   }
}
%hash = ('name' => 'Tom', 'age' => 19);

# Function call with hash parameter
PrintHash(%hash);

Quando il programma sopra viene eseguito, produce il seguente risultato:

name : Tom
age : 19

Restituzione di valore da una subroutine

Puoi restituire un valore dalla subroutine come fai in qualsiasi altro linguaggio di programmazione. Se non si restituisce un valore da una subroutine, qualsiasi calcolo eseguito per ultimo in una subroutine è automaticamente anche il valore di ritorno.

Puoi restituire array e hash dalla subroutine come qualsiasi scalare, ma restituire più di un array o hash normalmente fa perdere le loro identità separate. Quindi useremo i riferimenti (spiegati nel prossimo capitolo) per restituire qualsiasi array o hash da una funzione.

Proviamo il seguente esempio, che prende un elenco di numeri e quindi restituisce la loro media:

#!/usr/bin/perl

# Function definition
sub Average {
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_) {
      $sum += $item;
   }
   $average = $sum / $n;

   return $average;
}

# Function call
$num = Average(10, 20, 30);
print "Average for the given numbers : $num\n";

Quando il programma sopra viene eseguito, produce il seguente risultato:

Average for the given numbers : 20

Variabili private in una subroutine

Per impostazione predefinita, tutte le variabili in Perl sono variabili globali, il che significa che è possibile accedervi da qualsiasi punto del programma. Ma puoi creareprivate variabili chiamate lexical variables in qualsiasi momento con il my operatore.

Il myL'operatore confina una variabile a una particolare regione di codice in cui può essere utilizzata e accessibile. Al di fuori di tale regione, non è possibile utilizzare o accedere a questa variabile. Questa regione è chiamata il suo ambito. Uno scope lessicale è solitamente un blocco di codice con una serie di parentesi graffe attorno ad esso, come quelle che definiscono il corpo della subroutine o quelle che segnano i blocchi di codice delle istruzioni if, while, for, foreach ed eval .

Di seguito è riportato un esempio che mostra come definire una o più variabili private utilizzando my operatore -

sub somefunc {
   my $variable; # $variable is invisible outside somefunc()
   my ($another, @an_array, %a_hash); # declaring many variables at once
}

Controlliamo il seguente esempio per distinguere tra variabili globali e private:

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

# Function definition
sub PrintHello {
   # Private variable for PrintHello function
   my $string;
   $string = "Hello, Perl!";
   print "Inside the function $string\n";
}
# Function call
PrintHello();
print "Outside the function $string\n";

Quando il programma sopra viene eseguito, produce il seguente risultato:

Inside the function Hello, Perl!
Outside the function Hello, World!

Valori temporanei tramite local ()

Il localviene utilizzato principalmente quando il valore corrente di una variabile deve essere visibile alle subroutine chiamate. Un locale fornisce solo valori temporanei alle variabili globali (che significa pacchetto). Questo è noto come ambito dinamico . Lo scoping lessicale viene eseguito con my, che funziona più come le dichiarazioni automatiche di C.

Se vengono fornite più variabili o espressioni a local, devono essere inserite tra parentesi. Questo operatore funziona salvando i valori correnti di quelle variabili nel suo elenco di argomenti su uno stack nascosto e ripristinandoli all'uscita dal blocco, subroutine o eval.

Controlliamo il seguente esempio per distinguere tra variabili globali e locali:

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

sub PrintHello {
   # Private variable for PrintHello function
   local $string;
   $string = "Hello, Perl!";
   PrintMe();
   print "Inside the function PrintHello $string\n";
}
sub PrintMe {
   print "Inside the function PrintMe $string\n";
}

# Function call
PrintHello();
print "Outside the function $string\n";

Quando il programma sopra viene eseguito, produce il seguente risultato:

Inside the function PrintMe Hello, Perl!
Inside the function PrintHello Hello, Perl!
Outside the function Hello, World!

Variabili di stato tramite state ()

Esistono un altro tipo di variabili lessicali, che sono simili alle variabili private ma mantengono il loro stato e non vengono reinizializzate su più chiamate delle subroutine. Queste variabili vengono definite utilizzando ilstate operatore e disponibile a partire da Perl 5.9.4.

Controlliamo il seguente esempio per dimostrare l'uso di state variabili -

#!/usr/bin/perl

use feature 'state';

sub PrintCount {
   state $count = 0; # initial value

   print "Value of counter is $count\n";
   $count++;
}

for (1..5) {
   PrintCount();
}

Quando il programma sopra viene eseguito, produce il seguente risultato:

Value of counter is 0
Value of counter is 1
Value of counter is 2
Value of counter is 3
Value of counter is 4

Prima di Perl 5.10, dovresti scriverlo in questo modo:

#!/usr/bin/perl

{
   my $count = 0; # initial value

   sub PrintCount {
      print "Value of counter is $count\n";
      $count++;
   }
}

for (1..5) {
   PrintCount();
}

Contesto chiamata subroutine

Il contesto di una subroutine o di un'istruzione è definito come il tipo di valore restituito previsto. Ciò consente di utilizzare una singola funzione che restituisce valori diversi in base a ciò che l'utente si aspetta di ricevere. Ad esempio, il seguente localtime () restituisce una stringa quando viene chiamato in contesto scalare, ma restituisce un elenco quando viene chiamato nel contesto di elenco.

my $datestring = localtime( time );

In questo esempio, il valore di $ timestr è ora una stringa composta dalla data e dall'ora correnti, ad esempio Thu Nov 30 15:21:33 2000. Viceversa -

($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);

Ora le singole variabili contengono i valori corrispondenti restituiti dalla subroutine localtime ().