2012-03-04 42 views
11

Tôi bắt đầu học Common Lisp gần đây, và (chỉ để cho vui) quyết định đổi tên macro lambda.Đổi tên lambda trong Common Lisp

nỗ lực của tôi là thế này:

> (defmacro λ (args &body body) `(lambda ,args ,@body)) 

Dường như để mở rộng một cách chính xác khi tự:

> (macroexpand-1 '(λ (x) (* x x))) 
(LAMBDA (X) (* X X)) 

Nhưng khi nó được lồng vào bên trong một biểu thức, thực hiện thất bại:

> ((λ (x) (* x x)) 2) 
(Λ (X) (* X X)) is not a function name; try using a symbol instead 

Tôi có thể thiếu một cái gì đó rõ ràng về việc mở rộng vĩ mô, nhưng không thể tìm ra nó là gì.

Có thể bạn có thể giúp tôi?

chỉnh sửa: Nó làm việc với lambda:

> ((lambda (x) (* x x)) 2) 
4 

chỉnh sửa 2: Một cách để làm cho nó hoạt (theo đề nghị của Rainer):

> (set-macro-character #\λ (lambda (stream char) (quote lambda))) 

(thử nghiệm trong Clozure CL)

Trả lời

20

Trong Lisp phổ biến LAMBDA là hai thứ khác nhau: macro và biểu tượng có thể được sử dụng trong biểu thức LAMBDA.

Các LAMBDA biểu:

(function (lambda (x) (foo x))) 

ngắn viết như

#'(lambda (x) (foo x)) 

Một áp dụng biểu thức lambda cũng là hợp lệ:

((lambda (x) (+ x x)) 4) 

Trên cả hai hình thức là một phần của cú pháp cốt lõi của Lisp thường gặp.

Kết thúc định nghĩa của Common Lisp, macro được gọi là LAMBDA đã được thêm vào. Đủ lộn xộn, nhưng với ý định tốt. ;-) Nó được ghi nhận là Macro LAMBDA.

(lambda (x) (+ x x)) 

mở rộng vào

(function (lambda (x) (+ x x)) 

Nó làm cho mã Common Lisp trông hơi hơn như mã Đề án và sau đó nó không phải là cần thiết để viết

(mapcar #'(lambda (x) (+ x x)) some-list) 

Với LAMBDA vĩ mô chúng ta có thể viết

(mapcar (lambda (x) (+ x x)) some-list) 

Ví dụ của bạn không thành công vì

((my-lambda (x) (* x x)) 2) 

không hợp lệ Cú pháp Lisp chung.

Common Lisp hy vọng một trong hai

  • một đối tượng dữ liệu
  • một biến
  • một cuộc gọi chức năng theo hình thức (function args...)
  • một cuộc gọi chức năng theo hình thức ((lambda (arglist ...) body) args...)
  • một hình thức vĩ mô như (macro-name forms...)
  • một biểu mẫu đặc biệt bằng cách sử dụng một trong các toán tử đặc biệt được tích hợp ike FUNCTION, LET ... quy định tại danh mục special operators trong Common Lisp

Như bạn có thể thấy một cú pháp của

((macro-name forms...) forms...) 

không phải là một phần của Common Lisp.

Có thể đọc các nhân vật λ như LAMBDA:

(defun λ-reader (stream char) 
    (declare (ignore char stream)) 
    'LAMBDA) 

(set-macro-character #\λ #'λ-reader) 

Ví dụ:

CL-USER 1 > ((λ (x) (* x x)) 3) 
9 

CL-USER 2 > '(λ (x) (* x x)) 
(LAMBDA (X) (* X X)) 
+2

Nó không phải là 'hàm' trong việc mở rộng' lambda', đó là một vấn đề, đó là hành vi có dây cứng của các ứng dụng hàm với 'lambda'. Vì vậy, trong lời giải thích của bạn tôi sẽ thay đổi: "Một biểu thức lambda được áp dụng cũng hợp lệ" thành "Biểu thức' lambda' được áp dụng cũng hợp lệ (chỉ cho 'lambda' và không cho các macro mở rộng đến nó)". –

+0

Bây giờ, cảm giác thật tuyệt vời! Vì vậy, không có cách nào để có được (λ ...) để mô phỏng một biểu thức lambda? – ibab

+3

@qrl: cú pháp ((λ (x) ...) 4) là có thể với một macro đọc trong các triển khai CL hỗ trợ ký tự đó. Người đọc Lisp sẽ phải mở rộng λ vào LAMBDA. –

2

Bạn cũng có thể nghĩ về LAMBDA như một nhà điều hành mà, được đưa ra một thuật ngữ và danh sách miễn phí biến, trả về một hàm. P.o.v. đưa LAMBDA ra khỏi gia đình của các chức năng cơ bản và các macro cơ bản - ít nhất là đến chừng nào người phiên dịch có liên quan.

Các vấn đề liên quan