tiểu luận môn Nguyên lý các ngôn ngữ lập trình. Đề tài tìm hiểu về Lambda caculus

20 650 3
tiểu luận môn Nguyên lý các ngôn ngữ lập trình. Đề tài tìm hiểu về Lambda caculus

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG - - BÀI TẬP LỚN MÔN HỌC: NGUYÊN LÝ CÁC NGÔN NGỮ LẬP TRÌNH ĐỀ TÀI: TÌM HIỂU VỀ LAMBDA CACULUS GVHD: TS NGUYỄN HỮU ĐỨC HVTH: Nhóm (Dương Phú Thuần, Vũ Tuấn Vũ Thị Uyên, Trần Đăng Minh) Lớp: 12BCNTT2 Hà Nội, 12/2012 MỤC LỤC Giới thiệu phép tính lambda .1 Biểu diễn biểu thức lambda Scheme Định nghĩa hàm nhờ lambda 4 Kỹ thuật sử dụng phối hợp lambda Định nghĩa hàm nhờ tích luỹ kết 11 Tham đối hoá phần 14 Định nghĩa đệ quy cục 15 Kết luận………………………………………………………………………………… 18 Giới thiệu phép tính lambda Phép tính lambda (  -calculus) A Church đề xuất phát triển vào năm 1930 kỉ trước Phép tính lambda hệ thống quy tắc có khả biểu diễn, cho phép mã hóa tất hàm đệ quy (recursive functions) Phép tính lambda xem hàm phương pháp tính toán, khác với tiếp cận truyền thống toán học xem hàm tập hợp điểm có mối quan hệ với Cùng với lý thuyết máy Turing, phép tính lambda mô hình tính toán thực tính toán lớp hàm tính (calculable functions) Có hai cách tiếp cận phép tính lambda: tiếp cận túy (pure) dùng để nghiên cứu chiến lược tính hàm tiếp cận có định kiểu (typed) dùng để định kiểu biểu thức Mỗi cách tiếp cận dùng để biểu diễn cách tiếp cận Về mặt cú pháp, phép tính lambda sử dụng tập hợp Var gồm biến: x,y,z, , phép trừu tượng ký hiệu  áp dụng (application) để định nghĩa hạng (term) Người ta gọi t hạng  nếu:  t=x, với x  Var biến;  t=  x.M, với x  Var biến, M hạng  , gọi trừu tượng;  t=(MN) với M N hạng  , gọi áp dụng Ví dụ sau hạng  hay biểu thức  : (x,x)  x  y.(x(yz)  x.((xy)(xx)) ((  x.(xx))(  x.(xx))) Trong ngôn ngữ hình thức, giả sử gọi <  -t> hạng  , ta định nghĩa văn phạm G bảng chữ  sau: <  -t>::= ::=Var Một cách trực giác, phép trừu tượng  x.M thể hàm: x M áp dụng (MN) thể việc áp dụng hàm M cho tham đối N Người ta biểu diễn hạng  cú pháp Chẳng hạn hạng: (  x.(xy)(xx)) biểu diễn cú pháp sau (app áp dụng): Hình Cây biểu diễn biểu thức lambda Phép trừu tượng tác động lên biến Khi cần biểu diễn hàm có nhiều tham đối: x1,x2,…,xn  M người ta sử dụng kỹ thuật tham đối hóa phần (currying) để đưa dạng trừu tượng sử dụng biến:  x1.(  x2 …(  xn M) …) Để thuận tiện cho việc trình bày dễ đọc biểu thức lambda, người ta thường dùng quy ước sau: - Phép trừu tượng kết hợp phải:  x  y  z.M viết  xyz.M - Phép trừu tượng kết hợp trái: ((M N) P) viết M N P Ví dụ  x  y.((x y) z) viết :  xy.xyz Biểu diễn biểu thức lambda Scheme Trong Scheme, để biểu diễn cú pháp lambda hàm có hai tham số: (x, y)  x y người ta viết sau: ( lambda (x y) ( sqrt (+ x y))) Một cách tổng quát: (lambda arg- list body) đó, body s-biểu thức, arg- list dạng: x (x1 …) (x1 … xn-1 xn) Giá trị số biểu thức lambda hàm nặc danh (anonymous funtion), sử dụng tính toán để đưa kết cần phải cung cấp tham đối thực sự: ((lambda (x y) (sqrt (+ x y))) 13) > ((lambda (x y L) (cons x (cons y L))) ’a ’b ’c (c d)) > ’( a b c d) Để định hàm hằng, người ta sử dụng biểu thức lambda tham biến Ví dụ: (lambda () (display 1) (display “ Trong Scheme cú pháp định nghĩa hàm nhờ lambda sau: (define fname (lambda (x1 … xn) Body)) Dạng định nghĩa hàm dùng biểu thức lambda có lợi không phân biệt định nghĩa hàm với định nghĩa giá trị Scheme Tuy nhiên, người ta chuyển đổi từ dạng biểu thức lambda dạng định nghĩa hàm trước Ví dụ: (define (member? s L) (if (null? L) #f (or (equal? s (car L)) (member? s (cdr L))))) viết lại sau: (define my-member? (lambda (s L) (if (null? L) #f (or (equal? s (car L)) (define my-member? s L) Hàm sau cho phép chuyển đổi tự động dạng cũ thành dạng sử dụng lambda để định nghĩa hàm bất kỳ( ý định nghĩa hàm có sử dụng quasiquote): (define (oldform -> new form def-no-lambda) (let ((fname (caadr def-no-lambda)) (paramlist (caadr def-no-lambda)) (Lbody (cddr def-no- lambda))) (define, fname (lambda, paramlist, @Lbody)))) Vận dụng hàm oldform -> newform, ta chuyển hàm my-member? dạng định nghĩa nhờ lambda sau: (oldform -> newform ’(define (my- member? s L) (if (null? L) #f (or (equal? s (car L)) (my-member? s ( cdr L))))) > ‘ (define my – member? (if (null? (my – member? (lambra 1) #f (or s (adr (s L) (equai? s (car L)) L)))))) Hàm kết sử dụng hàm thông thường Chẳng hạn, ta xây dựng lại hàm sum-integer tính tổng số nguyên a b cho ví dụ trước sau: (define (sum (sum-integer a (lambra sum-integer (x) b) a b)) ; lời gọi (sum f x y) 9) > 45 (define (increnment (Lambra (y) ((Lambra (x) x) (= x (= x y))) L)) 2) 5)) 10) > ((Lambda (x) (+ x > 50 Nhờ phép tính lamđa, định nghĩa hàm trở nên gọn măt cú pháp: (define (double x) (+ x x)) tương đương với định nghĩa sử dụng lambda: (define double (lambde (double (x) (x x))) 5) > 10 Ví dụ sau liệt kê phần tử danh sách: (define (fo-each (display-list (lambda (display x) L) (x) (display “ “)) L)) (display-liste ‘ (a b c d e)) >a b c d e (display-liste ‘ (a (b ()) c (d) e )) Ta sử dụng lambda để xây dựng hàm tổ hợp sau: ;compose: (T2 →T3) (define x (T1→T2) → (T1 → 3) (compose (lambda (x) f f g) (g x))))) định nghĩa cách khác sau: (define compose (lambda (f (lambda args (f g) (apply g args))))) ((compose sqrt *) 12 75 Dùng lambda để xây dựng hàm incr nhận tham đối x, để trả hàm cho phép gia thêm lượng vào x (xem ví dụ mục trước): ; incr: (Number → Number) → ( Number → Number) ( define (x) (lambda (y) (+ x y))) ((inor 12) 5) > 17 Ta định nghĩa hàm incr2 cho phép tăng lên tham số: (define incr 2)) (define x 3) (incr 5) > 7; Kết Kỹ thuật sử dụng phối hợp lambda Dạng let tương đương với dạng lambda Chẳng hạn: (let ((x 1) (y 2)) (+ x y)) > ((lambda (x y) (+ x y)) 2) > Như vậy: (let ((x1 e1) ((lambda (x1 … xk) … (xk ek)) body) e1 … ek) Ta định nghĩa hàm sử dụng let phối hợp với lambda Chẳng hạn, để tính biểu thức a  b , ta định nghĩa hàm bổ trợ x nhờ lambda: (define (pitagore a b) (let ((sqr (lambda (x) (* x x)))) (sqrt (t (sqr a) (sqr b))))) (pitagore 4) >5 Với lambda, ta sử dụng kỹ thuật “ lời hứa tính toán” Chẳng hạn để mô dạng if tuỳ theo điều kiện để thực việc khác nhau, ta định nghĩa hàm chờ sau: (define (my- if x y z) (if x (y) (z))) (my- if (= 2) (lambda () #t) (lambda () #f)) > #f Ở cần sử dụng cặp dấu ngoặc để gọi lời hứa y z (define (fact n) ( my-if (= n 0) (lambda () 1) (lambda () (* n (fact (- n 1)))))) (fact 5) > 120 Định nghĩa hàm nhân: (define (mult-n n) (lambda (x) (*n x))) ((mult-n 9) 7) > 63 Giả sử cần viết thủ tục tạo sinh số tự nhiên: Gennerator: → Integer Cho phép liệt kê số nguyên lời gọi: (gennerator) > (gennerator) > (gennerator) > v.v …, ta sử dụng đột biến phần tử đôi danh sách sau: (define gennerator (let ((curr ( list -1))) (lambda () (set- car! Curr (+ ( car curr) 1)) ( car curr)))) (gennerator) > (gennerator) > (gennerator) > (gennerator) > Danh sách (-l) giá trị gán cho curr, tính lần thủ tục.Tuy nhiên curr luôn tính lại lần gọi đến thủ tục theo cách định nghĩa gặp lỗi sai: (define (gennrator) (define (set- car! (car curr Curr (+ ' ( - 1)) (car curr) 1)) curr) (gennrator) > Error: exception (set- car! ' (-1) 0) Do danh sách (-l) tạo lần cho trường hợp, định nghĩa thủ tục, lời gọi set- car! làm thay đổi lệnh thủ tục Về mặt lý thuyết, điều không với cú pháp ngôn ngữ Scheme Gennrato > (lambda () (define curr ' (-1))….) (gennrator) > Gennrator > (lambda () (define curr ' (0))….) Những sai sót kiểu thường xảy vô ý lập trình với đột biến Giả sử ta áp dụng hàm set! Scheme để làm thay đổi biến định nghĩa trước tồn (Hoặc tạo define, làm tham đối hàm khác) Hàm set! có cú pháp sau: (set! v s) Khi thực set!, scheme thay giá trị cũ biến v s Ví dụ: (define truc 1) truc > (set! truc 9999) truc > 9999 Chú ý hàm set! không trả kết Định nghĩa sau không biến toto chưa có (set! > toto 3) ERROR Sử dụng hàm set! để định nghĩa thủ tục tạo sinh số tự nhiên, ta gặp lỗi sai, luôn cho kết 0: (define (gennrator- e1) (define (set! curr curr - 1) (+ curr 1)) Curr) (gennrator- e1) > (gennrator- e1) > Định nghĩa sau sai, luôn cho kết 0: 10 (gennrator- e2) (define curr (set! - car! (car (list -1)) Curr (+ (car curr ) 1)) curr) (gennrator- e2) > (gennrator- e2) > Định nghĩa hàm nhờ tích luỹ kết Người ta thường gặp nhiều cấu trúc lập trình giống áp dụng cho nhiều hàm khác Sau đây, ta xét ví dụ áp dụng kỹ thuật tích luỹ kết nhờ hàm list-it 5.1 Tính tổng giá trị hàm áp dụng cho phần tử danh sách (define (if (sum h L) (null L) (+ (h (car L)) (product h (cdr L))))) 5.2 Tính tích giá trị hàm áp dụng cho phần tử danh sách (define (product (if (null? h L) L) (+ (h (car L)) (product h (cdr L))))) 11 5.3 Định nghĩa lại hàm append ghép hai danh sách (define (myappend (if (null? L1 L2) L1) L2 (cons (car L1) (myappend (cdr L1) L2)))) 5.4 Đ ịnh nghĩa lại hàm map cho hàm biến h (define (if (mymap (null? h L) L) ' () (cons (h (car L) (mymap h (cdr L))))) Giả sử danh sách L = (xo, x1…,xn), ta có cấu trúc chung hàm sau: (sum h L) = (+ (h x0) (+ (h x1) (+…(+ h xn) 0)…))) (product h L) = (* (h (myappend L x0) (* (h x1) (*…(* h xn) 0)…))) M) = (cons x0 (cons x0 (cons x1 (…(cons xn L2)…))) (mymap h L) = (cons (h x0) (cons (h x1) (…(cons (h xn) '())…))) Bằng cách sử dụng hàm f có đối số thứ danh sách L đối số thứ hai kết tích luỹ liên tiếp, giá trị cuối hàm là: (f x0 (f x1 (…(f xn R)…))) với R giá trị đầu 12 Từ ta dựng hàm list-it có tính tổng quát sau: (define (list-it f l R) (if (null? L) R (f (car L) (list-it f (cdr L) R)))) Hàm list-it thực hàm f cho phần tử danh sách L, kết tích luỹ R Sử dụng hàm list-it này, ta gọi để thực tính toán L hệt công việc bốn hàm viết lại sau (dòng ví dụ áp dụng): ; Hàm (sum (list-it (+ h L) (lambda (h x) (x y) y)) L 0) (list-it (lambda (x y) (+ (sprt x) y)) ' (1 5)0) > 8.38233 ; Hàm (product (list-it h L) (lambda (* (h (x y) x) y)) L 1) (list-it (lambda (x y) (* (sprt x) y)) ' (1 5) 1) > 10.9545 ; Hàm (myappend L1 L2) (list-it L1 L2) (list-it > cons cons ' (a b c ' (a b c) ' (1 2)) 2) ; Hàm (mymap h L) (list-it (lambda (x y) Cons (h x) (list-it Cons (lambda (sqrt L ' ()) (x y) x) > ' (1 1.41421 (map y)) y)) ' (1 5) ' ()) 1.73205 23607) (sqrt ' (1 5) ')) 13 > ' (1 1.41421 1.73205 23607) Chú ý áp dụng, cần cung cấp tham đối thực cho tham đối hàm h 5.5 Định nghĩa hàm fold Sau ta định nghĩa Scheme hai hàm fold foldl (left) foldr (right) nhận vào hàm f hai tham đối: phần tử xuất phát a danh sách L, để trả kết áp dụng liên tiếp (luỹ kế) hàm f cho a với phần tử L Hai hàm khác chỗ hàm fold lấy phần tử L từ trái qua phải, hàm foldl lấy phần tử L từ phải qua trái: (define (fold1 If (null? f a L) L) a (fold1 f (f (define (fold1 If (nu11? f a a (car L)) (cdr L)))) L) L) a (f (car L) (fold f (f a (car L)) (cdr L))))) (fold1 cons ’ ( 5)) > ’ (((((0 1) 2) 3) 4) 5) (foldr cons 0’ (1 5)) > ’( 0) Tham đối hoá phần Kỹ thuật tham đối hoá phần( currying) cho phép dùng biến để truy cập đến hàm số tham biến f(x1, …., xn) Chẳng hạn, hai hàm biến f(x,y) xem hàm biến x trả giá trị hàm y: x → (y → f(x,y)) 14 Giả sử xét hàm max tìm số lớn thư viện Scheme, với n=2: (max (* 5) 10) > 10 Sử dụng kỹ thuật Currying, ta viết: ( define ( curry2 f) (lambda (x) (lambda (y) (f x y)))) (((curry2 max) (* 5)) 10) > 10 Với n=3, ta xây dựng tương tự: (define (curry3 f) (lambda (x) (lambda (y) (lambda (z) (f x y z))))) (((curry3 max) (* 5)) 10) (+ 6)) > 10 Từ ta xây dựng cho hàm n đối Ưu tiên kỹ thuật Currying đặc tả hàm hay biết giá trị tham số thứ nhất, tham số cho hàm có nhiều hai tham đối Đối với hàm biến, ưu điểm kỹ thuật Currying người ta tổ hợp tuỳ ý hàm mà không quan tâm đến tham đối chúng Định nghĩa đệ quy cục Người ta sử dụng dạng hàm letrec thư viện Scheme để định nghĩa đệ quy hàm cục Chẳng hạn ta cần xây dựng danh sách số tự nhiên n với n cho trước sau: ; iota : number → list( number) ; iota: n → (0 … n) (define (iota n) ’(0) 15 (append (iota (-n 1)) (list n)))) (iota 10) > ’(0 10) Định nghĩa đắn, nhiên việc sử dụng hàm ghép danh sách append làm tốn nhớ, luôn phải thêm phần tử vào cuối danh sách Vì ý kiến cải biên làm ngược lại vấn đề: xây dựng hàm cho phép nhận số m để trả danh sách số tự nhiên từ m đến n (m m+1…n) Thay sử dụng hàm ghép danh sách, ta sử dụng cons để xây dựng hàm bổ trợ sau: (define (m-to-n (if (< n m n) m) ‘() (cons m (m-to-n (+ m 1) n)))) (m-to-n 0) > ‘ (3 10) Do hàm m-to-n không dùng đâu khác, nên cần đặt bên hàm iota Sau định nghĩa, cần gọi với hàm đổi m=0: (define (iota n) (define (if (m-to-n m n) ( < n m) ‘() (cons m (m-to-n (iota (m-to-n (+ m 1) n)))) n)) 10) > ‘ (0 10) Giả sử thay định nghĩa hàm cục m-to-n, ta sử dụng dạng let để tạo số tự nhiên kể từ m Tuy nhiên không cần dùng đến tham biến n n cấp hàm iota: (define (iota n) (let ((m-to-n (lambda (m) (if (< m n) 16 ’() (cons m (m-to-n (+ m 1) n)))) (m-to-n n)) (iota 10) > ’() Ta thấy kết sai lời gọi m-to-n hàm dẫn đến thực let lần mà không thực gọi đệ quy Để khắc phục, ta sử dụng dạng letrec, dạng let đặc biệt để tạo lời gọi đệ quy Cú pháp lectrec giống hệt let gồm phần liên kết phần thân: (lectrec ((v1 e1) … (vk en)) s) Các biến vi, i=1 N, gán giá trị ei để sau thực phần thân s biểu thức Tuy nhiên phép gán biến nhìn thấy lẫn nhau, nghĩa tính biểu thức ei sử dụng biến vi với i,j tuỳ ý Nghĩa không giống hoàn toàn let, biến cục vi….,vN nhìn thấy tất biểu thức e1,…ek Tuy nhiên, cần ý biểu thức ej tính mà không cần giá trị biến vj, ej biểu thức lambda Nhờ ngữ nghĩa này, dạng letrec thường sử dụng để định nghĩa thủ tục đệ quy tương hỗ (mutually recursive)… Chẳng hạn, vị trí từ odd ? even? trường hợp điển hình cho hàm thừa nhận định nghĩa đệ quy tương hỗ Sau ví dụ sử dụng letrec để định nghĩa tương hỗ hai thủ tục cục kiểm tra số nguyên chẵn (even) hay lẻ (odd) mà không sử dụng hai hàm thư viện Scheme even? odd?: (letrec ((local- even? ( lambda(n) (if (= n 0) #t (local- odd? (-n 1))))) (local- odd? ( lambda (n) (if (=n 0) #f 17 (local – even? (-n 1)))))) (list (local – even?27) ( local- odd? 27))) > ’(#f #t) Bây hàm iota định nghĩa lại sau: (define ( iota n) (lectrec ((m-to-n (lambda (m) (if (< n m) ’() (cons m (m-to-n (+ m 1) n)))) (m-to-n n)) (iota 10) > ’( 10) Sử dụng phối hợp dạng letrec lambda sau: ( lambda ( x1 … xn) ( lambda (x1 …xn) (define f1 e1) … (define fn en) s) (letrec (f1 e1) < = > … (fn en) s)) Kết luận Nhóm em tìm hiểu cách biểu diễn biểu thức lambda Scheme, cách định nghĩa hàm nhờ lambda, định nghĩa hàm nhờ tích lũy kết quả, kỹ thuật phối hợp sử dụng lambda, kỹ thuật tham đối hóa phần, định nghĩa đệ quy cục Phép tính lambda phát triển để trở thành công cụ quan trọng việc nghiên cứu vấn đề lý thuyết tính toán lý thuyết đệ quy, hình thành nên tảng mô hình lập trình hàm 18 [...]... dạng letrec và lambda như sau: ( lambda ( x1 … xn) ( lambda (x1 …xn) (define f1 e1) … (define fn en) s) (letrec (f1 e1) < = > … (fn en) s)) 8 Kết luận Nhóm em đã tìm hiểu được cách biểu diễn biểu thức lambda trong Scheme, cách định nghĩa hàm nhờ lambda, định nghĩa hàm nhờ tích lũy kết quả, kỹ thuật phối hợp sử dụng lambda, kỹ thuật tham đối hóa từng phần, định nghĩa đệ quy cục bộ Phép tính lambda đã được... cho mọi trường hợp, khi định nghĩa thủ tục, lời gọi set- car! làm thay đổi các lệnh của thủ tục Về mặt lý thuyết, điều này không đúng với cú pháp của ngôn ngữ Scheme Gennrato > (lambda () (define curr ' (-1))….) (gennrator) > 0 Gennrator 9 > (lambda () (define curr ' (0))….) Những sai sót kiểu này thường xảy ra do vô ý khi lập trình với đột biến Giả sử ta áp dụng hàm set! của Scheme để làm thay đổi... trị của biến vj, khi ej là một biểu thức lambda Nhờ ngữ nghĩa này, dạng letrec thường được sử dụng để định nghĩa các thủ tục đệ quy tương hỗ (mutually recursive)… Chẳng hạn, các vị trí từ odd ? và even? là trường hợp điển hình cho các hàm thừa nhận định nghĩa đệ quy tương hỗ Sau đây là ví dụ sử dụng letrec để định nghĩa tương hỗ hai thủ tục cục bộ kiểm tra một số nguyên là chẵn (even) hay lẻ (odd) mà... (curry3 f) (lambda (x) (lambda (y) (lambda (z) (f x y z))))) (((curry3 max) (* 2 5)) 10) (+ 2 6)) > 10 Từ đó ta có thể xây dựng cho hàm n đối bất kỳ Ưu tiên của kỹ thuật Currying là có thể đặc tả một hàm hay khi mới biết giá trị của tham số thứ nhất, hoặc các tham số đầu tiên cho các hàm có nhiều hơn hai tham đối Đối với hàm một biến, ưu điểm của kỹ thuật Currying là người ta có thể tổ hợp tuỳ ý các hàm... phần( currying) cho phép dùng biến để truy cập đến các hàm số tham biến bất kỳ f(x1, …., xn) Chẳng hạn, hai hàm biến f(x,y) được xem là hàm một biến x trả về giá trị như hàm y: x → (y → f(x,y)) 14 Giả sử xét hàm max tìm số lớn nhất trong thư viện Scheme, với n=2: (max (* 2 5) 10) > 10 Sử dụng kỹ thuật Currying, ta viết: ( define ( curry2 f) (lambda (x) (lambda (y) (f x y)))) (((curry2 max) (* 2 5)) 10)... phần thân: (lectrec ((v1 e1) … (vk en)) s) Các biến vi, i=1 N, được gán giá trị ei để sau đó thực hiện phần thân s là một biểu thức nào đó Tuy nhiên mỗi phép gán biến có thể nhìn thấy lẫn nhau, nghĩa là khi tính biểu thức ei thì có thể sử dụng các biến vi với i,j tuỳ ý Nghĩa là không giống hoàn toàn let, các biến cục bộ vi….,vN đều được nhìn thấy trong tất cả các biểu thức e1,…ek Tuy nhiên, cần chú ý... kỹ thuật tham đối hóa từng phần, định nghĩa đệ quy cục bộ Phép tính lambda đã được phát triển để trở thành một công cụ quan trọng trong việc nghiên cứu các vấn đề lý thuyết tính toán và lý thuyết đệ quy, và hình thành nên nền tảng cơ bản của mô hình lập trình hàm 18 ... cung cấp tham đối thực sự cho các tham đối là hàm h 5.5 Định nghĩa các hàm fold Sau đây ta định nghĩa trong Scheme hai hàm fold là foldl (left) và foldr (right) cùng nhận vào một hàm f hai tham đối: một phần tử xuất phát a và một danh sách L, để trả về kết quả là áp dụng liên tiếp (luỹ kế) hàm f cho a và với mọi phần tử của L Hai hàm khác nhau ở chỗ hàm fold lấy lần lượt các phần tử của L từ trái qua... 7 8 9 10) Định nghĩa trên đây đúng đắn, tuy nhiên việc sử dụng hàm ghép danh sách append làm tốn bộ nhớ, do luôn luôn phải thêm các phần tử mới vào cuối một danh sách Vì vậy ý kiến cải biên là làm ngược lại vấn đề: xây dựng hàm cho phép nhận một số m để trả về danh sách các số tự nhiên từ m đến n là (m m+1…n) Thay vì sử dụng hàm ghép danh sách, ta sử dụng cons để xây dựng hàm bổ trợ như sau: (define... lần lượt cho các phần tử của danh sách L, kết quả được tích luỹ bắt đầu từ R Sử dụng hàm list-it này, ta có thể gọi để thực hiện tính toán L hệt công việc của bốn hàm trên nhưng được viết lại như sau (dòng tiếp theo là ví dụ áp dụng): ; Hàm (sum (list-it (+ h L) (lambda (h x) (x y) y)) L 0) (list-it (lambda (x y) (+ (sprt x) y)) ' (1 2 3 4 5)0) > 8.38233 ; Hàm (product (list-it h L) (lambda (* (h

Ngày đăng: 17/04/2016, 21:25

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan