You are on page 1of 27

TRƯỜNG ĐẠI HỌC BÁCH KHOA

KHOA CÔNG NGHỆ THÔNG TIN

LẬP TRÌNH HÀM


Võ Trung Hùng
Hung.Vo-Trung@ud.edu.vn
Nội dung
„ Nguyên lý lập trình hàm
„ Ngôn ngữ Scheme
„ Kiểu dữ liệu phức hợp
„ Kỹ thuật xử lý hàm
„ Cấu trúc dữ liệu
Phương pháp
„ Lý thuyết
– Nắm được mục đích từng nội dung
– Cách thức tiến hành
– Những vấn đề cần lưu ý
„ Thực hành
– Thực hành các nội dung đã học
– Nắm được các kỹ năng lập trình
„ Thực hiện báo cáo
Tài liệu tham khảo
„ Giáo trình lập trình hàm (P.H. Khánh)
„ Revised Report on Algorithmic Language
Scheme, Richard Kelsey, Wiliam Clinger
& Jonathan Rees
„ Teach Yourself Scheme in Fixnum Days,
Dorai Sitaram
„ PLT DrScheme : Programming Env.
Manual, http://www.drscheme.org/
Phần I
Nguyên lý lập trình hàm
Định nghĩa ngôn ngữ lập trình
„ Bộ ký tự (character set)
„ Bộ từ vựng (vocabulary)
– Từ khóa
– Tên, định danh
– Phép toán
– ...
„ Cú pháp (syntax)
„ Ngữ nghĩa (semantic)
Lập trình mệnh lệnh
„ Sử dụng nguyên lý tinh chế từng bước
„ Khai báo dữ liệu : tên biến - kiểu
„ Các kiểu dữ liệu cơ bản : số, ký tự...
„ Trạng thái trong (bộ nhớ, thanh ghi) thay đổi
bằng lệnh gán
„ Trạng thái ngoài (thiết bị ngoại vi) thay đổi bởi
các lệnh vào ra
„ Các cấu trúc điều khiển
„ Dễ có hiệu ứng phụ khi dùng CT con
Cơ sở của các ngôn ngữ hàm (1)

„ Tính khai báo


– Ngôn ngữ mệnh lệnh :
begin
GetData (...);
ProcessData(...);
OutputData(...);
end
– Ngôn ngữ lập trình hàm
(print
(process-data
(get-data (...))))
Cơ sở của các ngôn ngữ hàm (2)
„ Đặc điểm
– Là NNLT bậc cao trừu tượng hơn
– Ít sử dụng các biến toàn cục
– Người sử dụng quan tâm đến việc định nghĩa
các hàm toán học dễ suy luận mà không quan
tâm đến vấn đề cài đặt
– Ngôn ngữ lập trình hàm dựa trên việc tính toán
giá trị của biểu thức từ bên ngoài lời gọi hàm
– Một hàm có thể có hoặc không có đối số
Cơ sở của các ngôn ngữ hàm (3)

„ Đặc điểm
– Kết quả một hàm không phụ thuộc vào thời
điểm hàm được gọi
f(x) + f(x) = 2 * f(x) ?
– Không thể thay đổi giá trị một phân tử của mảng
– Hạn chế trong giao tiếp giữa hệ thống tương tác
với HĐH và NSD
Cơ sở của các ngôn ngữ hàm (3)

„ Các khái niệm cơ bản trong LTH


– Hàm (function)
– Danh sách (list)
– Kiểu (type)
– Tính đa kiểu (polymorphism)
– Các hàm bậc cao (higher-order function)
– Tham đối hoá từng phần (currying)
– Các hàm theo kiểu khôn ngoan (lazy-evalation)
– Phương trình (equation)
Ngôn ngữ Miranda

„ Giới thiệu
– Do David Turner phát triển năm 1986
– Trình thông dịch chạy trên Unix
– Đặc điểm : thuần tuý hàm
„ Định nghĩa hàm
– Cú pháp
<tên hàm> ::<miền xác định> -><miền giá trị>
<tên hàm>[<danh sách tham đối>]=<biểu thức> [<điều
kiện>]
Ngôn ngữ Miranda

„ Định nghĩa hàm


– Ví dụ : đổi độ Fahrenheit --> Celsius
celsius :: num -> num
celsius f = (f - 32) * 5 / 9
– Sử dụng :
celsius 68
--> 20
Ngôn ngữ Miranda

„ Định nghĩa hàm


– Ví dụ : tính ước số chung lớn nhất gcd (greatest
common divisor)
gcd :: num -> num
gcd a b = gcd (a-b) b, if a>b
= gcd a (b-a), if b>a
= a, if a=b

– Sử dụng :
gcd 4 2
--> 2
Ngôn ngữ Miranda

– Ví dụ : tính giai thừa


fac :: num -> num
fac n = 1, if n=0
fac x = x * fac(x - 1), otherwise
– Sử dụng :
fac 4
--> 24
Ngôn ngữ Miranda

– Ví dụ : tìm nghiệm phương trình bậc 2


ptbac2 a b c
= error "PT vo nghiem", if delta<0
= [-b/(2*a)], if delta=0
= [-b/(2*a)] + radix/(2*a), otherwise
= [-b/(2*a)] - radix/(2*a), otherwise
where delta=b*b-4*a*c and radix=sqrt delta
– Sử dụng :
ptbac2 2 1 -3
--> 1
-1.5
Ngôn ngữ Miranda

„ Danh sách
– Đây là cấu trúc dữ liệu quan trọng nhất của các
ngôn ngữ lập trình hàm
[1, 4, 9, 16] II danh sách gồm 4 số nguyên
[1..10] II danh sách gồm 10 số nguyên
['a', 'b', 'c'] II danh sách gồm 3 ký tự
[] II danh sách rỗng
weekdays=["Mon", "Tue", "Wed", "Thur", "Fri"]
– Dạng nhận biết được : [body I qualifiers]
[n | n <- [1..10] : n mod 2 = 1]
--> [1, 3, 5, 7, 9]
Ngôn ngữ Miranda

„ Danh sách
– Một số các phép toán trên danh sách
ƒ product [...] : tính tích
fac n = product [1..n]
ƒ sum [...] : tính tổng
resul = sum [1, 3..100]
ƒ hd [...] : trả về phần tử đầu tiên
hd [1, 3, 100] --> 1
ƒ tl [...] : trả về danh sách các PT thứ 2 -->
tl [1, 3, 2, 5] --> [3, 2, 5]
ƒ : [...] : chèn 1 PT vào đầu danh sách
0 : [1, 3, 2, 5] --> [0, 1, 3, 2, 5]
Ngôn ngữ Miranda

„ Danh sách
– Viết lại một số hàm
ƒ length L = 0, if L = []
length L = 1 + length (tl L), otherwise
ƒ concat L1 L2 = L2, if L1 = []
concat L1 L2 = L1, if L2 = []
concat L1 L2
= (hd L1) : concat (tl L1) L2, otherwise
Ngôn ngữ Miranda

„ Phép so khớp
– Một hàm có thể định nghĩa bằng nhiều biểu thức
vế phải khác nhau
– Cú pháp tổng quát :
<pattern> = <expression>, <condition>
– Ví dụ : tính dãy Fibonacci
fib 0 = 0
fib 1 = 1
fib (n+2) = fib (n+1) + fib n
Ngôn ngữ Miranda

„ Phép so khớp
– Ví dụ : tính độ dài chuỗi
length [] = 0
length (a : L) = 1 + (length L)
– Ví dụ : tính tổng của mảng
sum [] = 0
sum [a : X] = a + sum X
– Ví dụ : tính tích của mảng
product [] = 1
product [a : X] = a * product X
Ngôn ngữ Miranda

„ Phương pháp currying (tham đối hoá từng


phần - partial parametrization)
– Cho hàm n biến : f(x1, x2,..., xn)
– Có thể viết lại :
x1-->(x2-->...(xn-->f(x1..xn))...))
– Một hàm nhiều hơn 1 tham đối thì có thể tham
đối hoá từng phần
triple x = 3 * x
hoặc
triple = multi 3
Ngôn ngữ Miranda

„ Kiểu và tính đa kiểu (polymorphic)


– Các ngôn ngữ hàm thường không sử dụng định
kiểu
– Cho phép định nghĩa các hàm đa kiểu với lời gọi
có các tham đối có các kiểu dữ liệu khác nhau
– Ví dụ
pair x y = [x, y]
– Sử dụng
pair 1 2 --> [1, 2]
pair true false --> [true, false]
Ngôn ngữ Miranda

„ Tính hàm theo kiểu khôn ngoan


– Thông thường khi tính giá trị một hàm, các tham
đối được tính giá trị trước --> tính giá trị của hàm
mult (fac 3) (fac 4) --> mul 6 24 --> 144
– Rút gọn biểu thức --> đơn giản hơn : rút gọn theo
thứ tự áp dụng
mult (fac 3) (fac 4) --> (fac 3) * (fac 4)
– Ví dụ
cond b x y = x, if b
cond b x y = y, otherwise
Ngôn ngữ Miranda
„ Tính hàm theo kiểu khôn ngoan
– Ví dụ : tính fac với cond
fac n = cond (n = 0) 1 (n * fac (n-1))
--> nếu tham đối thứ 3 luôn được tính thì hàm
trong Miranda chỉ tính giá trị tham đối khi cần
Ex : fac 1
--> cond (1=0) 1 (1*fac (1-1)) II gọi fac
--> if (1=0) then 1 else (1*fac (1-1)) II gọi cond
--> if false then 1 else (1*fac (1-1)) II tính 1=0
--> 1*fac (1-1)
--> 1*(cond (1-1=0) 1 ((1-1)*fac ((1-1)-1)))
--> ...
Ngôn ngữ Miranda

„ Một vài ví dụ :
– Loại bỏ những phần tử trùng nhau
uniq [] = []
uniq (a:(a:L) = uniq (a:L)
uniq (a:L) = a : uniq L
Ex :
uniq [3, 3, 4, 6, 6, 6, 6, 7]
--> [3, 4, 6, 7]
uniq ['a', 'b', 'b', 'c', 'c']
--> ['a', 'b', 'c']
Ngôn ngữ Miranda

„ Một vài ví dụ :
– Sắp xếp nhanh
quicksort [] = []
quicksort (x:Tail)
= quicksort [a  a <-- Tail :a<x]
quicksort [a  a <-- Tail :a>x]
Ex :
Quicksort [5, 2, 9, 1]
--> [1, 2, 5, 9]

You might also like