Perl - Chương trình con

Chương trình con Perl hoặc hàm là một nhóm các câu lệnh cùng thực hiện một nhiệm vụ. Bạn có thể chia mã của mình thành các chương trình con riêng biệt. Cách bạn phân chia mã của mình giữa các chương trình con khác nhau là tùy thuộc vào bạn, nhưng về mặt logic, việc phân chia thường là để mỗi hàm thực hiện một nhiệm vụ cụ thể.

Perl sử dụng các thuật ngữ chương trình con, phương thức và chức năng thay thế cho nhau.

Xác định và gọi một chương trình con

Dạng tổng quát của định nghĩa chương trình con trong ngôn ngữ lập trình Perl như sau:

sub subroutine_name {
   body of the subroutine
}

Cách gọi chương trình con Perl thông thường như sau:

subroutine_name( list of arguments );

Trong các phiên bản của Perl trước 5.0, cú pháp để gọi các chương trình con hơi khác như hình dưới đây. Điều này vẫn hoạt động trong các phiên bản Perl mới nhất, nhưng nó không được khuyến khích vì nó bỏ qua nguyên mẫu chương trình con.

&subroutine_name( list of arguments );

Hãy xem ví dụ sau, nó định nghĩa một hàm đơn giản và sau đó gọi nó. Vì Perl biên dịch chương trình của bạn trước khi thực thi nó, nên việc bạn khai báo chương trình con ở đâu không quan trọng.

#!/usr/bin/perl

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

# Function call
Hello();

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

Hello, World!

Chuyển các đối số đến một chương trình con

Bạn có thể chuyển các đối số khác nhau vào một chương trình con giống như bạn làm trong bất kỳ ngôn ngữ lập trình nào khác và chúng có thể được ghi vào bên trong hàm bằng cách sử dụng mảng đặc biệt @_. Do đó, đối số đầu tiên của hàm là $ _ [0], đối số thứ hai là $ _ [1], v.v.

Bạn có thể truyền các mảng và hàm băm dưới dạng đối số giống như bất kỳ đại lượng vô hướng nào nhưng việc truyền nhiều hơn một mảng hoặc hàm băm thông thường khiến chúng mất đi danh tính riêng biệt. Vì vậy, chúng tôi sẽ sử dụng các tham chiếu (được giải thích trong chương tiếp theo) để chuyển bất kỳ mảng hoặc băm nào.

Hãy thử ví dụ sau, lấy một danh sách các số và sau đó in giá trị trung bình của chúng -

#!/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);

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

Average for the given numbers : 20

Chuyển danh sách đến chương trình con

Vì biến @_ là một mảng, nó có thể được sử dụng để cung cấp danh sách cho một chương trình con. Tuy nhiên, do cách Perl chấp nhận và phân tích cú pháp các danh sách và mảng, có thể khó trích xuất các phần tử riêng lẻ từ @_. Nếu bạn phải chuyển một danh sách cùng với các đối số vô hướng khác, thì hãy tạo danh sách làm đối số cuối cùng như hình dưới đây:

#!/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);

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

Given list is 10 1 2 3 4

Chuyển các hàm băm cho các chương trình con

Khi bạn cung cấp hàm băm cho chương trình con hoặc toán tử chấp nhận một danh sách, thì hàm băm sẽ tự động được dịch thành danh sách các cặp khóa / giá trị. Ví dụ -

#!/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);

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

name : Tom
age : 19

Trả lại giá trị từ một chương trình con

Bạn có thể trả về một giá trị từ chương trình con giống như bạn làm trong bất kỳ ngôn ngữ lập trình nào khác. Nếu bạn không trả về giá trị từ chương trình con thì bất kỳ phép tính nào được thực hiện lần cuối trong chương trình con cũng tự động trở thành giá trị trả về.

Bạn có thể trả về các mảng và hàm băm từ chương trình con giống như bất kỳ hàm vô hướng nào nhưng việc trả về nhiều hơn một mảng hoặc hàm băm thường khiến chúng mất đi các danh tính riêng biệt. Vì vậy, chúng tôi sẽ sử dụng tham chiếu (giải thích trong chương tiếp theo) để trả về bất kỳ mảng hoặc băm nào từ một hàm.

Hãy thử ví dụ sau, lấy một danh sách các số và sau đó trả về giá trị trung bình của chúng -

#!/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";

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

Average for the given numbers : 20

Biến riêng trong chương trình con

Theo mặc định, tất cả các biến trong Perl là biến toàn cục, có nghĩa là chúng có thể được truy cập từ bất kỳ đâu trong chương trình. Nhưng bạn có thể tạoprivate các biến được gọi là lexical variables bất cứ lúc nào với my nhà điều hành.

Các mytoán tử giới hạn một biến trong một vùng mã cụ thể mà nó có thể được sử dụng và truy cập. Bên ngoài khu vực đó, biến này không thể được sử dụng hoặc truy cập. Vùng này được gọi là phạm vi của nó. Phạm vi từ vựng thường là một khối mã với một tập hợp các dấu ngoặc nhọn xung quanh nó, chẳng hạn như các dấu ngoặc nhọn xác định phần thân của chương trình con hoặc các khối mã đánh dấu các khối mã của các câu lệnh if, while, for, foreacheval .

Sau đây là một ví dụ cho bạn thấy cách xác định một hoặc nhiều biến riêng bằng cách sử dụng my nhà điều hành -

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

Hãy kiểm tra ví dụ sau để phân biệt giữa biến toàn cục và biến riêng:

#!/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";

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

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

Giá trị tạm thời qua cục bộ ()

Các localchủ yếu được sử dụng khi giá trị hiện tại của một biến phải được hiển thị cho các chương trình con được gọi. Local chỉ cung cấp các giá trị tạm thời cho các biến toàn cục (nghĩa là gói). Đây được gọi là phạm vi động . Lexical scoping được thực hiện với my, hoạt động giống như khai báo tự động của C.

Nếu nhiều biến hoặc biểu thức được cấp cho cục bộ, chúng phải được đặt trong dấu ngoặc đơn. Toán tử này hoạt động bằng cách lưu các giá trị hiện tại của các biến đó trong danh sách đối số của nó trên một ngăn xếp ẩn và khôi phục chúng khi thoát khỏi khối, chương trình con hoặc eval.

Hãy kiểm tra ví dụ sau để phân biệt giữa các biến toàn cục và cục bộ:

#!/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";

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

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

Biến trạng thái qua trạng thái ()

Có một loại biến từ vựng khác, tương tự như biến private nhưng chúng duy trì trạng thái của chúng và chúng không được khởi động lại khi có nhiều lần gọi chương trình con. Các biến này được xác định bằng cách sử dụngstate và có sẵn bắt đầu từ Perl 5.9.4.

Hãy kiểm tra ví dụ sau để chứng minh việc sử dụng state biến -

#!/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();
}

Khi chương trình trên được thực thi, nó tạo ra kết quả sau:

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

Trước Perl 5.10, bạn sẽ phải viết nó như thế này -

#!/usr/bin/perl

{
   my $count = 0; # initial value

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

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

Ngữ cảnh cuộc gọi chương trình con

Ngữ cảnh của chương trình con hoặc câu lệnh được định nghĩa là kiểu giá trị trả về được mong đợi. Điều này cho phép bạn sử dụng một hàm duy nhất trả về các giá trị khác nhau dựa trên những gì người dùng mong đợi nhận được. Ví dụ: localtime () sau đây trả về một chuỗi khi nó được gọi trong ngữ cảnh vô hướng, nhưng nó trả về một danh sách khi nó được gọi trong ngữ cảnh danh sách.

my $datestring = localtime( time );

Trong ví dụ này, giá trị của $ timestr hiện là một chuỗi được tạo thành từ ngày và giờ hiện tại, ví dụ: Thứ Năm, ngày 30 tháng 11 15:21:33 2000. Ngược lại -

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

Bây giờ các biến riêng lẻ chứa các giá trị tương ứng được trả về bởi chương trình con localtime ().