2014-09-06 19 views
7

Tôi đang cố gắng hiểu việc sử dụng lambda trong vợt và tôi vẫn chưa rõ ràng. Tôi nhận được rằng họ không có tên (vô danh) chức năng nhưng tại sao là tốt? Tôi cần truy cập các chức năng của mình từ các chức năng khác để tôi gọi chúng như thế nào ??? Vui lòng giải thích chương trình nhỏ bên dưới và tại sao sử dụng lambda thì tốt hơn? Cảm ơn bạn.Lambda trong Vợt Giải thích

; why is this better than below??? 
(define test 
    (lambda (x) 
    (lambda (y) 
     (+ x y)))) 

(define add27 
    (test 27)) 

; what's wrong with this??? 
(define (addTest x) 
    (+ x 27)) 

> (add27 2) 
29 
> (addTest 2) 
29 

Trả lời

10

Trong vợt (và các ngôn ngữ lập trình chức năng khác) lambda s là rất hữu ích, khi bạn muốn vượt qua một dòng, chức năng one-shot như một tham số mà không cần xác định trước. Ví dụ, giả sử chúng ta muốn tạo một danh sách các số. Chúng ta có thể đi theo con đường dài và xác định một hàm square đầu tiên, và sau đó sử dụng map:

(define (square x) 
    (* x x)) 

(map square '(1 2 3 4 5)) 
=> '(1 4 9 16 25) 

... Hoặc chúng ta có thể dễ dàng vượt qua một lambda, như thế này:

(map (lambda (x) (* x x)) 
    '(1 2 3 4 5)) 

=> '(1 4 9 16 25) 

Như bạn có thể thấy, có các trường hợp tồn tại mà chúng tôi không cần để tham chiếu đến tên của hàm. Tất nhiên, nếu các thủ tục đại diện bởi các lambda sẽ được tái sử dụng trong một số bộ phận, hoặc nếu nó là đệ quy sau đó nó làm cho tinh thần để cung cấp cho nó một cái tên (do đó, nó không còn vô danh):

(define square 
    (lambda (x) (* x x))) 

Ở trên là tương đương với định nghĩa đầu tiên của square ngay từ đầu. Trong thực tế, định nghĩa đầu tiên chỉ là cú pháp cú pháp để xác định hàm, nhưng cuối cùng là tất cả các hàm là lambdas!

Bây giờ, hãy xem ví dụ của bạn. Ở đây chúng ta đang sử dụng một lambda một cách hơi khác nhau, và cũng có thể minh họa tại sao họ đang hữu ích - chúng tôi không chỉ định một chức năng, nhưng trở về một chức năng cũng như:

(define test 
    (lambda (x) 
    (lambda (y) 
     (+ x y)))) 

Có lẽ đó sẽ là một chút rõ ràng hơn nếu chúng ta viết nó như thế này (đó là tương đương, vì những lý do nêu trên):

(define (test x) 
    (lambda (y) 
    (+ x y))) 

Hoặc thậm chí ngắn hơn - trong Racket chúng tôi cũng có thể sử dụng cú pháp này cho cùng một mục đích:

(define ((test x) y) 
    (+ x y)) 

Nó không phải là một tốt hơn (hoặc tồi tệ hơn) cách để xác định một chức năng - đó là một điều khác nhau! chúng tôi đang xác định một thủ tục gọi là test, nhận được tham số x và trả về kết quả là một hàm ẩn danh mới, do đó sẽ nhận được tham số y. Bây giờ, trong những dòng này:

(define add27 
    (test 27)) 

... chúng tôi đang gọi điện thoại test với một giá trị x của 27, mà trả về chức năng ẩn danh, và chúng tôi tên có chức năng add27. Hãy nhớ số lambda nhận được làm tham số y? bây giờ là lambda đã được đặt tên là add27 - và đây là ví dụ về currying.Nghĩ về nó: test là một chức năng được sử dụng để tạo ra các chức năng mà thêm một giá trị cố định x đến một tham số cho y, giải thích lý do tại sao công trình này:

(add27 2) 
=> 29 

Mặt khác, chức năng này sẽ luôn luôn thêm 27 với thông số của nó mà không có cách nào để thay đổi thông số:

(define (addTest x) 
    (+ x 27)) 

(addTest 2) 
=> 29 

Bạn thấy sự khác biệt? test cho phép chúng tôi tạo các hàm mới có thêm giá trị tùy ý, trong khi addTest luôn thêm một giá trị cố định, 27. Nếu bạn muốn thêm lời nói, 100 thì sao? sử dụng test này rất đơn giản:

(define add100 (test 100)) 

Nhưng addTest không thể thay đổi, chúng tôi sẽ cần phải viết một hàm mới:

(define (addTest100 x) 
    (+ x 100)) 

Tôi hy vọng điều này làm rõ điều này, đừng ngần ngại hỏi trong các ý kiến bất kỳ câu hỏi nào khác về câu trả lời của tôi.

+1

Cảm ơn bạn rất nhiều vì lời giải thích này. Tôi vẫn đang cố gắng hiểu nó hoạt động như thế nào nhưng đây là một khởi đầu tuyệt vời. Bây giờ tôi chỉ cần đọc lại nó 500 lần. =) – 1Raptor007

+0

Tôi xin lỗi nhưng tôi vẫn chưa rõ cách thức này trả về một hàm. Tôi không hiểu. – 1Raptor007

+1

@ 1Raptor007 một hàm trả về giá trị cuối cùng. Ví dụ, điều này trả về '1' khi được gọi:' (define (f) 1) '. Và cho rằng một 'lambda' cũng là một giá trị giống như bất kỳ cái nào khác, nếu chúng ta viết cái này:' (define (f) (lambda (x) x)) 'thì chúng ta có một hàm, khi được gọi, sẽ trả về kết quả một chức năng nặc danh –