I. Tương tác với FILE
sub sub_name { #
Subroutines (gọi tắt là sub) trong perl tương đương với hàm trong C/C++. Một sub sẽ thực hiện một quá trình nào đó và khi ứng dụng chính cần sẽ gọi sub vào thực hiện công việc. Ví dụ như print, open, close, …. chính là các sub đã được khai báo sẵn trong thư viện perl, chỉ cần gọi và sử dụng cho hợp lý.
Cách khai báo một sub như sau:
sub sub_name { # #
# statements …. # #
}
Từ khóa sub cho biết bạn đang tạo sub với tên là sub_name, và khi sử dụng bạn sẽ gọi tên này cùng với các đối số truyền vào bên trong thân sub. Khác với trong C, bạn phải khai báo tên và số lượng các đối số truyền vào sub, perl thì không cần như vậy và bạn có thể truyền vào được rất nhiều đối số. Để nhận lấy các giá trị đối số, trong than sub bạn cần sử dụng mảng @_ để lấy các giá trị được truyền vào. Khác với C/C++, giá trị trả về (return value) của perl có thể là bất cứ cái gì, nếu bạn không sử dụng return thì giá trị đánh giá của biểu thức cuối cùng trong sub sẽ được lấy ra.
Để gọi một sub, đơn thuần chỉ cần gọi tên sub và đối số nếu có; bạn có thể sử dụng kí tự & trước tên sub. Ví dụ chương trình tính tổng một dãy các số: -SCRIPT- #!/usr/bin/perl -w use strict; my @listA = qw/0 1 2 3 4 5 6/; my @listB = qw/1.1 2.2 3.3/; sub calculate_sum { my @list = @_; my $sum = 0; foreach my $i (@list) { $sum += $i; } $sum
}
print "Sum ListA = ", calculate_sum(@listA), "\n"; print "Sum ListB = ", calculate_sum(@listB), "\n";
-/SCRIPT-
Bạn có thể thấy 2 mảng @listA và @listB có kiểu dữ liệu khác nhau và số lượng phần tử khác nhau nhưng calculate_sum() đều thực hiện việc tính tổng các phần tử một cách linh hoạt.
Trong calculate_sum(), biểu thức cuối cùng mình viết chỉ là tên của biến $sum, nhưng nó được đánh giá và làm giá trị trả về cho hàm.
Một điều chú ý trong perl là nếu tiếp sau có dấu } thì bạn không cần gõ dấu ; để kết thúc
Thử phân tích một ví dụ khác về các cách gọi một hàm: -SCRIPT- #!/usr/bin/perl -w # @file: sub.pl use strict; sub print_name { print "Bạn tên là: $_[0] \n"; } print_name("JaPh"); #1 print_name "JaPh"; #2 &print_name("JaPh"); #3 &print_name; #4 -/SCRIPT-
Bạn chạy script trên shell như sau:
$ perl sub.pl JaPh
Cách gọi #1 giống với trong ngôn ngữ C, gọi tên hàm và sử dụng cặp dấu ngoặc đơn để truyền vào tham số. Đây là cách phổ biến trong khi viết code perl hiện nay vì tính gần gũi và dễ hiểu.
Cách gọi #2 không sử dụng cặp dầu ngoặc đơn. Trình dịch perl sẽ tìm kiếm ở trên xem hàm print_name() đã có khai báo hay chưa, nếu như phần code trước khi gọi mà print_name() chưa được khai báo thì sẽ xảy ra lỗi.
-SCRIPT-
#!/usr/bin/perl -w # @file: sub.pl use strict;
print_name "JaPh"; #2: có lỗi
print_name("JaPh"); #1 &print_name("JaPh"); #3 &print_name; #4 sub print_name { print “Bạn tên là: $_[0] \n"; } -/SCRIPT-
Còn viết như sau là hợp lệ:
-SCRIPT-
#!/usr/bin/perl -w # @file: sub.pl use strict;
sub print_name; # khai báo ở đây rồi nên không có lỗi print_name("JaPh"); #1 print_name "JaPh"; #2 &print_name("JaPh"); #3 &print_name; #4 sub print_name { print "Bạn tên là: $_[0] \n"; } -/SCRIPT-
Cách gọi #3 tương đương với cách gọi #1.
Cách gọi #4 ở đây không truyền vào bất kì một tham số nào; vì vậy theo mặc định, trình dịch perl sẽ lấy
@_ vào làm tham số cho print_name(). Như mình đã nói ở trên cách chạy script, có truyền vào tham số
“JaPh” vì thế cách gọi #4 sẽ lấy giá trị đầu tiên của @_, tức là $_[0].
Một điều thú vị nữa về hàm trong perl đó là, bạn có thể lưu một hàm như một biến scalar dưới dạng tham chiếu, hay còn gọi là tham chiếu hàm.
Để gán một biến scalar tham chiếu tới một hàm bạn sử dụng kí hiệu: \&tên_hàm . Để thực thi biến scalar tham chiếu tới hàm bạn sử dụng dấu -> để gọi.
Thử cùng xem ví dụ sau về tham chiếu hàm
-SCRIPT-
#!/usr/bin/perl -w # @file: sub_ref.pl use strict;
sub print_name {
print "Ban ten la: $_[0] \n"; }
my $print_name_ref = \&print_name; # gán tham chiếu $print_name_ref->("JaPh"); # thực thi
-/SCRIPT-
Nếu như khi thực thi bạn không sử dụng dấu truy xuất tham chiều -> thì chương trình sẽ báo lỗi. Một trong những ứng dụng nổi bật nhất của tham chiếu hàm trong perl đó là subroutine-callback, hay có thể hiểu là truyền hàm vào và sử dụng như một biến. Kiểu này tương đương với con trỏ hàm function pointer để callback trong ngôn ngữ C/C++.
Cùng xét ví dụ sau để thấy rõ hơn mục đích của sub callback.
-SCRIPT- #!/usr/bin/perl -w #!/usr/bin/perl -w # @file: sub_callback.pl use strict; # phép tính cộng sub calc_plus { my ($a, $b) = @_; return ($a + $b); } # phép tính trừ sub calc_minus { my ($a, $b) = @_; return ($a - $b); }
# hàm thực hiện phép tính và gọi callback sub calculate {
my ($func, $a, $b) = @_; $func->($a, $b);
}
# kiểm tra callback
print "9 - 5 = ", calculate(\&calc_minus, 9, 5), "\n";
-/SCRIPT-
Ở đây có 2 hàm thực hiện phép tính toán calc_plus() và calc_minus(), và một hàm calculate() thực hiện việc tính toán thông qua việc gọi hàm tính toán thực sự làm tham số (callback).
Trong hàm calculate(), calc_plus() và calc_minus() được gán vào biến $func, sẽ thực hiện việc tham chiếu tới hàm gốc vì vậy hàm sẽ được gọi tương ứng. Sub-Callback trong perl khá là quen thuộc với function pointer và callback trong ngôn ngữ C.
Sách được viết và biên soạn bởi [JaPh] @ 2010
Nếu ai có nhu cầu muốn đưa nội dung sách lên blog, web để làm hướng dẫn xin hãy liên hệ tác giả trước.
Nghiêm cấm việc sử dụng sách vào mục đích thương mại hay kiếm lợi nhuận.
Mọi góp ý, thắc mắc và hỏi đáp xin liên hệ qua email: pete.houston.17187@gmail.com Thông tin về sách sẽ thường xuyên được cập nhật tại blog của tác giả:
http://xjaphx.blogspot.com/
Xin chân thành cảm ơn các bạn đã quan tâm. Tác giả,