2.8 Ngôn ngữ lập trình hàm OCaml
2.8.2 Cú pháp và ngữ nghĩa .1 Biến.1Biến
OCaml là ngôn ngữ hằng nên biến thực chất là giá trị được đặt tên và không thể thay đổi trong một phạm vi nào đó trong suốt quá trình chạy [14]. Điều này có nghĩa là khi lập trình viên gán giá trị cho biến thì sau đó không thể thay đổi giá trị cho biến đó. OCaml cung cấp kiểu tham chiếu (mutable references), nó giống như là các con trỏ. Các biến tham chiếu này có thể thay đổi giá trị mà nó trỏ tới.
2.8.2.2 Kiểu dữ liệu cơ bản
Bảng 2.1: Các kiểu dữ liệu cơ bản của OCaml
Kiểu dữ liệu Mô tả
int Kiểu nguyên dương 31-bit
float Kiểu số thực
bool Kiểu logic bao gồm true hoặc false
char Kiểu kí tự
string Chuỗi ký tự
unit Kiểu đặc biệt
OCaml cung cấp các kiểu dữ liệu cơ bản được liệt kê trong Bảng 2.1. Kiểu int chỉ sử dụng 32 bits tại vì nó sử dụng 1 bit để phân biệt giữa số nguyên và con trỏ. Nếu lập trình viên muốn sử dụng số nguyên 32-bit thì có thể sử dụng Int32 hoặc sổ nguyên 64-bit thì có thể sử dụng Int64.
2.8.2.3 Hàm
Hàm là một đối tượng dữ liệu nhận vào gồm có các tham số và trả về một đối tượng dữ liệu có kiểu [14]. Một hàm có thể nhận và trả về một kiểu dữ liệu OCaml hợp lệ bất kỳ, bao gồm kết quả trả về là một hàm khác. Hàm được định
Chương 2.Kiến thức cơ bản
SimpleExpression:
AdditiveExpr Expression:
OrExpr
Hình 2.25: Định nghĩa biểu thức.
nghĩa bằng cách sử dụng từ khóa let, f un hoặc f unction. Tuy nhiên, hàm yêu cầu có ít nhất một tham số.
Hình 2.28 định nghĩa một hàm đơn giản nhất. Hàm có tên làmy f uncnhận tham số là một kiểu unit và trả về giá trị là một kiểu int. Hàm được kết thúc bằng hai dấu chấm phẩy. Hình 2.29 mô tả cách gọi hàm trong OCaml. Hàm phải có duy nhất một kiểu trả về, mặc dù kiểu trả về có thể là kiểu đa hình. Kiểu mà hàm trả về sẽ được trình biên dịch tự động đưa ra. Trình biên dịch tìm kiểu thông dụng nhất mà hàm có thể trả về và sau đó sử dụng kiểu đó.
2.8.2.4 Hàm mức cao
OCaml hỗ trợ hàm mức cao [14]. Điều này có nghĩa là hàm có thể nhận một hàm khác làm tham số. Sở dĩ OCaml làm được điều này vì OCaml xem hàm như là các lớp dữ liệu cơ bản. Hình 2.30 là ví dụ minh họa hàmbiggernhận ba tham số đầu vào. Tham số f đầu tiên là một hàm có hai tham số. Hai tham số cuối cùng x,yđược xem như là tham số của tham số f.
2.8.2.5 Hàm nặc danh
Hàm nặc danh là hàm không có tên, vì vậy hàm không được gán bất kỳ một giá trị nào [14]. Hàm nặc danh rất hữu ích trong OCaml. Nhiều hàm sử dụng các hàm khác như là đối số và hàm nặc danh là cách dễ dàng khai báo và đưa vào làm tham số cho các hàm khác. Thông thường, khai báo hàm nặc danh bằng cách sử dụng từ khóa f unhoặc f unction. Hàmcomparedùng để so sánh hai giá trị trong việc sắp xếp một danh sách. Hàm nhận vào hai số nguyên và trả về giá trị là 1 nếu giá trị thứ hai bé hơn giá trị thứ nhất. Hàm trả về giá trị là 0 nếu giá trị thứ hai bằng giá trị thứ nhất và trả về giá trị là -1 nếu giá trị thứ hai lớn hơn giá trị thứ nhất. Hàmcomparecó thể được cài đặt riêng biệt rồi sử dụng nó. Tuy nhiên, với hàm nặc danh có thể giúp khai báo và sử dụng trực tiếp chính nó.
Hình 2.31 mô tả một hàm nặc danh.
Chương 2.Kiến thức cơ bản
OrExpr:
AndExpr
OrExpr||AndExpr AndExpr:
BitOrExpr
AndExpr&&BitOrExpr BitOrExpr:
BitExclOrExpr
BitOrExpr|BitExclOrExpr BitExclOrExpr:
BitAndExpr
BitExclOrExpr∧BitAndExpr BitAndExpr:
EqualityExpr
BitAndExpr&EqualityExpr EqualityExpr:
RelationalExpr
EqualityExpr==RelationalExpr EqualityExpr!==EqualityExpr RelationalExpr:
ShiftExpr
RelationalExpr<ShiftExpr RelationalExpr<=ShiftExpr RelationalExpr>ShiftExpr RelationalExpr>=ShiftExpr ShiftExpr:
AdditiveExpr
ShiftExprằAdditiveExpr ShiftExprôAdditiveExpr
Hình 2.26: Định nghĩa biểu thức (tiếp).
2.8.2.6 Hàm đệ quy
Hàm đệ quy là một phần cực kỳ quan trọng của OCaml [14]. Hiệu suất và Kích thước mã nguồn của chương trình được cải tiến nhờ khả năng đệ quy đuôi trong OCaml. Hàm nặc danh không thể sử dụng đệ quy đuôi. Bởi vì hàm nặc danh không có tên nên không thể gọi hàm đó được. Hàm đệ quy được khai báo trong OCaml bằng cách thêm từ khóa rec trước tên của hàm đó. Hàm đệ quy trong OCaml là đệ quy đuôi nếu nó đảm bảo hai yêu cầu sau: hàm đệ quy không chứa try/with và giá trị trả về phải là giá trị không đổi. Ví dụ, hàm tính số Fibonacci không phải là hàm đệ quy đuôi [14]. Bởi vì, hàm tính số Fibonacci trả về giá trị là hàm yêu cầu tính giá trị Fibonacci tiếp theo. Hình 2.32 mô tả một hàm đệ quy tính số Fibonacci.
2.8.2.7 So sánh mẫu
OCaml cung cấp một chức năng so sánh mẫu tương tự với cấu trúcSW ITCH...
CASE của C/C++, Java [14]. Các quyết định đưa ra được dựa vào cấu trúc và
Chương 2.Kiến thức cơ bản
AdditiveExpr:
MultiplicativeExpr
AdditiveExpr+MultiplicativeExpr AdditiveExpr-MultiplicativeExpr MultiplicativeExpr:
UnaryExpr
MultiplicativeExpr*UnaryExpr MultiplicativeExpr\UnaryExpr MultiplicativeExpr%UnaryExpr UnaryExpr:
BaseExpr +BaseExpr -BaseExpr
!BaseExpr BaseExpr:
IntegerLiteral Variable ConstantIdent
’ActionLabel
#SetIdent
@(SetIdent , Expression) (Expression)
Hình 2.27: Định nghĩa biểu thức (tiếp).
# l e t myfunc ( ) = 1 + 1 ; ;
v a l myfunc : u n i t −> i n t = <fun>
Hình 2.28: Ví dụ khai báo hàm.
giá trị đầu vào. Cấu trúc lệnh của so sánh mẫu được mô tả ở Hình 2.33. Trình biên dịch OCaml sẽ so sánh expression với các patternn để đưa ra quyết định thực hiệnexpressionn tương ứng. Ví dụ so sánh mẫu được mô tả ở Hình 2.34.
2.8.2.8 Đối tượng
OCaml là ngôn ngữ lập trình hàm được phát triển dựa trên ngôn ngữ CAML và có thêm chức năng hướng đối tượng [14]. OCaml cung cấp đầy đủ các nguyên lý của hướng đối tượng như: lớp, đối tượng, thừa kế, đa hình.
# myfunc 2 ; ;
− : i n t = 4
Hình 2.29: Ví dụ gọi hàm.
Chương 2.Kiến thức cơ bản
# l e t b i g g e r f x y = f x y ; ;
v a l b i g g e r : ( 'a −> 'b −> 'c ) −> 'a −> 'b −> 'c = <fun>
# b i g g e r ( > ) 10 2 0 ; ;
− : bool = f a l s e
# b i g g e r ( < ) 10 2 0 ; ;
− : bool = t r u e
Hình 2.30: Ví dụ hàm mức cao.
# L i s t . s o r t (fun x y −> i f x = y then
−1
e l s e i f x < y then 1
e l s e 0
) [ 1 ; 4 ; 9 ; 3 ; 2 ; 1 ] ; ;
− : i n t l i s t = [ 9 ; 4 ; 3 ; 2 ; 1 ; 1 ]
Hình 2.31: Ví dụ hàm nặc danh.
# l e t r e c f i b n = i f ( n < 2 ) then 1
e l s e
( f i b ( n − 1 ) ) + ( f i b ( n − 2 ) ) ; ; v a l f i b : i n t −> i n t = <fun>
# f i b 6 ; ;
− : i n t = 13
Hình 2.32: Ví dụ hàm đệ quy.
match expression with
| pattern1-> expression1
| pattern2-> expression2 ...
| patternn-> expressionn
Hình 2.33: Cấu trúc lệnh của so sánh mẫu.
# l e t f i = match i with
| o −> " Zero "
| 3 −> " Three "
| _ −> " Neith er zero nor t h r e e " ; ;
Hình 2.34: Ví dụ so sánh mẫu.
Chương 2.Kiến thức cơ bản