Learning Perl - Chương 8: Hàm
1. Xác định một hàm tiện ích
2. Gọi một hàm tiện ích
3. Giá trị trả về
4. Đối số của hàm
5. Biến cục bộ trong hàm
6. Bài tập
Chúng ta đều đã thấy và đã dùng các hàm được thiế kế sẵn (có sẵn) như chop, print...Bây giờ ta
hãy nhìn vào các hàm mà bạn định nghĩa ra, tạo nên các lệnh chương trình Perl.
8.1 Xác định một hàm tiện ích
Một hàm tự tạo, thường hay được gọi là chương trình con hay trình con, được xác định trong
chương trình Perl của bạn bằng việc dùng một kết cấu như:
sub subname {
cau lenh 1;
cau lenh 2;
cau lenh 3;
....
}
subname là tên của chương trình con, là bất kì tên nào giống như tên ta đã đặt cho biến vô
hướng, mảng và mảng băm (cho nên bạn có thể có một biến vô hướng $jerry, một mảng
@jerry, một mảng kết hợp %jerry, và bây giờ một trình con jerry.
Khối các câu lệnh đi sau tên trình con trở thành định nghĩa của trình con. Khi trình con được
gọi tới (được mô tả ngắn gọn), thì khối các câu lệnh tạo nên trình con này sẽ được thực hiện,
và bất kì giá trị trả về nào (được mô tả sau đây) đều được trả về cho nơi gọi.
Chẳng hạn sau đây là một trình con cho hiển thị câu nói nổi tiếng:
sub say_hello {
print "Xin chao moi nguoi!\n";
}
Định nghĩa trình con có thể ở bất kì đâu trong văn bản chương trình của bạn, nhưng bạn nên
đặt tất cả các trình con vào cuối tệp, để cho phần còn lại của chương trình có vẻ như là ở đầu
tệp. (Nếu bạn thích nghĩ theo kiểu Pascal thì bạn có thể đặt các trình con của mình vào đầu và
$a + $b;
}
Bạn cũng có thể dùng câu lệnh return để trả về giá trị từ trình con:
sub sum_of_a_and_b {
return $a + $b;
}
Biểu thức cuối cùng được tính trong thân của trình con này (trong thực tế, đó là biểu thức duy
nhất được tính) là tổng của $a và $b, cho nên tổng của $a và $b sẽ là giá trị cho lại. Sau đây là
thí dụ:
$a = 3; $b = 4;
$c = sum_of_a_and_b(); #$c = 7
$d = 3*sum_of_a_and_b(); #$d = 21
Một trình con cũng có thể cho lại một danh sách các giá trị khi được tính trong hoàn cảnh
mảng. ta hãy xét trình con này và lời gọi:
sub list_of_a_and_b {
($a, $b);
}
$a = 3; $b = 4;
@c = list_of_a_and_b(); #@c = (5, 6)
Biểu thức cuối được tính thực sự nghĩa là biểu thức cuối cùng được tính, thay vì là biểu thức
cuối cùng được xác định trong thân của trình con. Chẳng hạn, trình con này cho lại $a nếu $a >
0, ngoài ra nó cho $b:
sub gime_a_or_b {
if ($a > 0) {
print "chon a ($a)\n";
$a;
} else {
print "chọn b ($b)\n";
$b;
}
}
say("hello", "world"); #hello, world!
say ("goodbye", "cruel world");
Các tham biến vượt quá đều bị bỏ qua - nếu bạn chưa bao giờ xem tới $_[3], thì đối với Perl
cũng không sao. Các tham số không đủ cũng bị bỏ qua - bạn đơn thuần nhận được undef nếu
bạn nhìn vượt ra phần tử cuối của mảng @_, như với mọi mảng khác.
Biến @_ là cục bộ cho trình con này; nếu có một biến toàn cục cho @_, nó sẽ được cất giữ
trước khi trình con được gọi và được khôi phục lại giá trị trước của nó khi trở về từ chương
trình con. Điều này cũng có nghĩa là một trình con có thể truyền các đối cho một trình con khác
mà không sợ mất biến @_ riêng của nó - việc gọi trình con lồng nhau đều nhận được @_ riêng
của nó theo cùng cách.
Ta hãy xem xét lại trình con "cộng a và b" của mục trước. Tại đây một trình con thực hiện việc
cộng hai giá trị bất kì, đặc biệt, hai giá trị được truyền cho trình con này như tham biến.
sub add_two {
$_[0] + $_[1];
}
print add_two(3, 4); #in 7
$c = add_two(5, 6); #$c = 11
Bây giờ ta hãy tổng quát hoá chương trình này. Nếu chúng ta có ba, bốn hay hàng trăm giá trị
cần phải cộng lại thì sao? Chúng ta có thể làm việc đó bằng một chu trình, tựa như:
sub add {
$sum = 0 ; #khoi dong gia tri cho $sum
foreach $_ (@_ ) {
$sum += $_ ; #cong tung phan tu
}
$sum ; #bieu thuc cuoi duoc tinh: tong cua tat ca cac
phan tu,
#hoac ban co the dung return $sum;
}
$a = add(4,5,6) ; #cong 4+5+6 = 15, va gan cho $a
Sau đây là cách để tạo ra một danh sách tất cả các phần tử có giá trị lớn hơn 100 của một mảng
lớn:
sub bigger_than_100 {
my (@result);
foreach $_ (@_ ) { #duyet qua danh sach
if ($_ > 100) { #kiem tra xem co lon hon 100?
push (@result, $_); #day vao danh sach
}
return @result ; #tra ve ket qua
}
Điều gì xảy ra nếu chúng ta muốn tất cả các phần tử này lớn hơn 50 thay vì 100? Chúng ta phải
sửa chương trình này, đổi tất cả các số 100 thành 50. Nhưng điều gì xảy ra nếu chúng ta lại cần
cả hai? Được, chúng ta có thể thay thế 50 hay 100 bằng một biến tham khảo. Điều này làm
chương trình trông giống thế này:
sub bigger_than {
my ($n, @values); #tao ra cac biet cuc bo
($n, @values) = @_; #khoi tao gia tri cho bien cuc bo,
thuc chat la lay gia tri tu cac tham so
my (@result); #them 1 bien cuc bo nua
foreach $_ (@values) { #duyet danh sach cac gia tri
if ($_ > $n) { #phan tu nay co gia tri lon hon $n
(=50, 100 hay gia tri nao do)
push (@result, $_) ; #dua vao danh sach neu hop le
}
return @result; #tra ve ket qua
}
#vi du
@new = bigger_than(100, @list); #tim cac phan tu lon hon 100 trong
mang @list
@this = bigger_than(5,1,5,15,30); #tim cac phan tu lon hon 5 trong