Tham khảo tài liệu ''giáo trình phân tích khả năng ứng dụng đối tượng dữ liệu mang bộ mô tả kiểu động p9'', công nghệ thông tin, cơ sở dữ liệu phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả
h a n g e Vi e y N c • Các hàm điều khiển - (IF E1 E2 E3) nhận vào biểu thức E1, E2 E3 Nếu E1 khác NIL hàm trả giá trị E2 ngược lại trả giá trị E3 - (IF E1 E2) tương đương (IF E1 E2 NIL) - Nếu E2 khác NIL (IF E1 E2 E3) tương đương (OR (AND E1 E2) E3) (COND (ÐK1 E1) (ÐK2 E2) (ÐKn En) [(T En+1)] ) Nếu ĐK1 khác NIL trả kết giá trị E1, ngược lại xét ĐK2 Nếu ĐK2 khác NIL trả kết giá trị E2, ngược lại xét ĐK3 Nếu ĐKn khác NIL trả kết giá trị En, ngược lại trả NIL trả kết giá trị En+1 (trong trường hợp ta sử dụng (T En+1)) - (PROGN E1 E2 En) nhận vào n biểu thức E1, E2, En Hàm định trị biểu thức E1, E2, En từ trái sang phải trả kết giá trị biểu thức En - (PROG1 E1 E2 En) nhận vào n biểu thức E1, E2, En Hàm định trị biểu thức E1, E2, En từ trái sang phải trả kết giá trị biểu thức E1 Hàm người lập trình định nghĩa Cú pháp định nghĩa hàm là: (defun ) Ví dụ 1: Ðịnh nghĩa hàm lấy bình phương số a (defun binh_phuong (a) (* a a) ) Sau nạp hàm cho LISP, ta sử dụng hàm định nghĩa trước >(binh_phuong 5) = 25 >(binh_phuong (+ 2)) = 49 Ví dụ 2: Ðịnh nghĩa hàm DIV chia số a cho số b, lấy phần nguyên 89 bu to k d o m o o c u -tr a c k w lic w w w d o Chương VIII: Lập trình hàm m C lic k to bu Ngơn ngữ lập trình w w w C y N O W ! XC er O W F- w PD h a n g e Vi e ! XC er PD F- c u -tr a c k c h a n g e Vi e y N c Trước hết ta có: a DIV b = (a – a MOD b)/b (defun DIV (a b) (/ (- a (MOD a b)) b) ) 8.3.4 Ðệ quy Một hàm đệ quy hàm có lời gọi biểu thức định nghĩa hàm Mơ tả đệ quy bao gồm: • Có trường hợp “dừng” để kết thúc việc gọi đệ quy • Lời gọi đệ quy phải bao hàm yếu tố dẫn đến trường hợp “dừng” Ví dụ 1: Viết hàm tính n giai thừa ⎧1 neu n = Cơng thức đệ quy tính n giai thừa n! = ⎨ ⎩ n * (n − 1)! Hàm (giai_thua N) viết ngôn ngữ LISP: (defun giai_thua (n) (if (= n 0) ; trường hợp “dừng” (* n (giai_thua (1- n))); n-1 yếu tố dẫn đến trường hợp dừng ) ; If ) Ví dụ 2: Viết hàm DIV chia a cho b lấy phần nguyên, viết đệ quy ⎧ neu a < b Công thức đệ quy: a DIV b = ⎨ ⎩1 + (a − b) DIV b Hàm (DIV a b) viết LISP: (defun DIV (a b) (if (< a b) ; Trường hợp “dừng” (1+ (DIV (- a b) b)); a-b yếu tố dẫn đến trường hợp dừng ) ; If ) Ví dụ 3: Viết hàm (phan_tu i L), nhận vào số nguyên dương i danh sách L Hàm trả phần tử thứ i danh sách L thông báo “không tồn tại” Công thức đệ quy: " Khong ton tai" neu DS L rong ⎧ ⎪ Phan tu thu i DS L = ⎨ Phan tu dau tien cua L neu i = ⎪Phan tu thu (i − 1) DS " duoi" cua L ⎩ Hàm (phan_tu i L) viết LISP: (defun phan_tu(i L) (cond ((Null L) “Khong ton tai”) ((= i 1) (car L)); trường hợp dừng thứ hai (T (phan_tu (1- i) (cdr L))) 90 bu to k d o m o o c u -tr a c k w lic w w w d o Chương VIII: Lập trình hàm m C lic k to bu Ngơn ngữ lập trình w w w C y N O W ! XC er O W F- w PD h a n g e Vi e ! XC er PD F- c u -tr a c k c h a n g e Vi e c u -tr a c k w y N c ) ; cond ) Trong chương trình trên, (null L) trường hợp “dừng” thứ nhất; (= i 1) trường hợp “dừng” thứ hai; (cdr L) yếu tố dẫn đến trường hợp “dừng” thứ (1- i) yếu tố dẫn đến trường hợp “dừng” thứ hai 8.3.5 Các hàm nhập xuất • (LOAD ) Nạp tập tin vào cho LISP trả T việc nạp thành công, ngược lại trả NIL Tên tập tin chuỗi kí tự bao gồm đường dẫn đến nơi lưu trữ tập tin Tên tập tin theo quy tắc DOS, nghĩa có tối đa ký tự phần tên ký tự phần mở rộng không chứa ký tự đặc biệt Ta sử dụng LOAD để nạp tập tin chương trình LISP trước gọi thực hàm định nghĩa tập tin Ví dụ: >(Load “D:\btlisp\bai1.lsp”) • (READ) Ðọc liệu từ bàn phím gõ phím Enter, trả kết liệu nhập từ bàn phím • (PRINT E) In hình giá trị biểu thức E, xuống dòng trả giá trị E • (PRINC E) In hình giá trị biểu thức E (khơng xuống dịng) trả giá trị E • (TERPRI) Ðưa trỏ xuống dòng trả NIL 8.3.6 Biến toàn cục biến cục Biến toàn cục Biến toàn cục (global variables) biến mà phạm vi tất hàm Biến tồn cục tự động giải phóng chương trình dịch LISP kết thúc • Hàm (SETQ ) Gán trị cho trả kết giá trị Ví dụ: >(setq x (* 3)) =6 > x ; biến x cịn tồn có giá trị 91 bu to k lic d o m o m w o d o Chương VIII: Lập trình hàm w w w w w C lic k to bu Ngôn ngữ lập trình C y N O W ! XC er O W F- w PD h a n g e Vi e ! XC er PD F- c u -tr a c k c w y N O W ! PD k to bu Chương VIII: Lập trình hàm c =6 Biến cục Biến cục (local variables) biến mà phạm vi nằm hàm mà tạo Biến cục tự động giải phóng hàm tạo kết thúc • (LET ( (var1 E1) (var2 E2) (vark Ek)) Ek+1 En) Ta thấy hàm có phần: phần gán trị cho biến phần định trị biểu thức Gán trị biểu thức Ei cho biến cục vari tương ứng thực (PROGN Ek+1 En) Ví dụ: >(Let ((a 3) (b 5)) (* a b) (+ a b)) =8 > a ; biến a lúc giải phóng nên LISP thông báo lỗi error: unbound variable - A Biến cục che biến tồn cục Trong lập trình hàm, người ta hạn chế sử dụng biến, thật cần thiết nên sử dụng biến cục Tuy nhiên việc khai báo biến cục hàm LET gây khó khăn cho việc viết chương trình sử dụng biến tồn cục Để khắc phục tình trạng này, ta kết hợp hai hàm LET SETQ để sử dụng biến cục che biến toàn cục Cách làm sau: - Trong phần gán trị cho biến LET ta tạo biến gán cho giá trị bất kỳ, chẳng hạn số - Trong phần định trị biểu thức, ta sử dụng SETQ để gán trị cho biến tạo trên, biến biến cục khơng cịn tồn cục - Cụ thể viết: (LET ( (var E1)… ) …… (SETQ var E2) …… ) Với cách làm biến var hàm SETQ trở thành biến cục Ví dụ: Giả sử ta định nghĩa hàm (ptb2 a b c), giải phương trình bậc hai ax2+bx+c = Bây ta viết hàm (giai_ptb2) cho phép nhập hệ số a, b, c từ bàn phím gọi hàm (ptb2 a b c) để thực việc giải phương trình Có hai phương pháp để viết hàm Phương pháp 1: dùng biến toàn cục a, b, c (defun giai_ptb2 () (progn (print “Chương trình giải phương trình bậc hai“) 92 d o m o m w o c u -tr a c k h a n g e Vi e lic O W N y bu to k lic C Ngơn ngữ lập trình w w d o XC er w w w F- w C h a n g e Vi e ! XC er PD F- c u -tr a c k c h a n g e Vi e y N c (princ “Nhập hệ số a: “) (setq a (read)) (princ “Nhập hệ số b: “) (setq b (read)) (princ “Nhập hệ số c: “) (setq c (read)) (ptb2 a b c) ) ) Sau thực chương trình này, biến tồn cục a, b c cịn Phương pháp 2: dùng biến cục d, e, f (defun giai_ptb2 () (let ((d 0) (e 0) (f 0)) (print “Chương trình giải phương trình bậc hai“) (princ “Nhập hệ số a: “) (setq d (read)) (princ “Nhập hệ số b: “) (setq e (read)) (princ “Nhập hệ số c: “) (setq f (read)) (ptb2 d e f) ) ) Sau thực chương trình này, biến cục d, e f giải phóng 8.3.7 Hướng dẫn sử dụng LISP Sử dụng XLISP XLISP trình thơng dịch, chạy hệ điều hành Windows Chỉ cần chép tập tin thực thi XLISP.EXE có dung lượng 288Kb vào máy tính bạn thực Để thực hàm, cần gõ trực tiếp hàm vào sau dấu chờ lệnh (>) XLISP Trong trường hợp khơng có dấu chờ lệnh, dùng menu Run/Top level Ctrl-C để làm xuất dấu chờ lệnh Việc định nghĩa hàm gõ trực tiếp vào sau dấu chờ lệnh Tuy nhiên cách làm khó sửa chữa hàm ta thường định nghĩa hàm tập tin chương trình, sau nạp vào cho XLISP để sử dụng Ta lưu trữ lại tình trạng làm việc hành vào tập tin WKS cách dùng menu File/Save workspace sau khơi phục lại cách dùng menu File/Restore workspace Soạn thảo tập tin chương trình Do XLISP khơng có cơng cụ để soạn thảo chương trình nên ta sử dụng Notepad để soạn thảo tập tin chương trình Trong tập tin chương trình ta định nghĩa nhiều hàm Lưu tập tin chương trình có tên theo quy định DOS (8.3) với phần mở rộng LSP để cặp dấu nháy kép 93 bu to k d o m o o c u -tr a c k w lic w w w d o Chương VIII: Lập trình hàm m C lic k to bu Ngôn ngữ lập trình w w w C y N O W ! XC er O W F- w PD h a n g e Vi e ! XC er PD F- c u -tr a c k c ... chương trình Do XLISP khơng có cơng cụ để soạn thảo chương trình nên ta sử dụng Notepad để soạn thảo tập tin chương trình Trong tập tin chương trình ta định nghĩa nhiều hàm Lưu tập tin chương trình. .. trình hàm, người ta hạn chế sử dụng biến, thật cần thiết nên sử dụng biến cục Tuy nhiên việc khai báo biến cục hàm LET gây khó khăn cho việc viết chương trình sử dụng biến tồn cục Để khắc phục... “) (setq f (read)) (ptb2 d e f) ) ) Sau thực chương trình này, biến cục d, e f giải phóng 8.3.7 Hướng dẫn sử dụng LISP Sử dụng XLISP XLISP trình thơng dịch, chạy hệ điều hành Windows Chỉ cần