2010-07-25 30 views
12

Lý do cơ bản đằng sau quyết định thiết kế để có các không gian tên riêng cho các giá trị và hàm trong Common Lisp là gì? Các đối số cho và chống lại nó là gì?Tại sao nhiều không gian tên?

Trả lời

7

Lisp thông thường về cơ bản là hậu duệ của bản gốc Lisp 1.5, hay đúng hơn là một sự thống nhất các phương ngữ phân tách của nó. Bản gốc Lisp 1.5 là ngày nay được gọi là Lisp-2. Bởi vì nó đã trở lại vào những năm sáu mươi và thực tế là bạn có thể vượt qua các chức năng cho các chức năng khác là đủ kỳ lạ. Không ai có thể nghĩ đến việc cho phép họ chia sẻ cùng một không gian tên. Hầu như bất kỳ ngôn ngữ nào được phát minh ngày nay với sự hỗ trợ cho các hàm bậc cao và các hàm ẩn danh chọn cách tiếp cận không gian tên đơn. Bao gồm Clojure, mà là nếu không gần gũi hơn với Common Lisp hơn để Đề án.

Đề án, như Clojure, ban đầu không phải là một phương ngữ phân biệt từ Lisp 1.5, và cho mục đích của chúng có ý nghĩa. Tất nhiên, trong Clojure, vectơ, bản đồ băm, tập hợp và tất cả cũng có thể được áp dụng cho đối số, do đó, trong một ý nghĩa, một vector trong Clojure có thể được xem như một hàm lấy số tự nhiên và tạo ra một giá trị từ cái đó.

+3

(Có lẽ cũng đáng nói rằng một hàm trong lisp cũ) tương tự như một hàm trong Emacs Lisp - chỉ là một danh sách bắt đầu bằng 'lambda'.) –

+0

Thật sao? Tôi không ý kiến. Vì vậy, họ chỉ thay đổi các biến ràng buộc mức thấp trong eval trước khi áp dụng nó? Chết tiệt, điều đó phải tốn kém. – Zorf

+0

Rich Hicky nói về cách anh tránh được một số cạm bẫy bình thường đi kèm với Lisp-1. (tìm clojure trên blib.tv). Tôi không thể nhớ chính xác vì vậy bạn muốn tự mình giải thích nó. – nickik

4

Tôi thực sự thích có một số không gian tên (thậm chí nhiều hơn hai không gian); nó làm cho mọi thứ dễ dàng hơn cho người sử dụng và trình biên dịch-nhà văn (thực hiện):

CL-USER> (defclass test()()) 
#<STANDARD-CLASS TEST> 
CL-USER> (defun test()) 
TEST 
CL-USER> (defparameter test 42) 
TEST 

CL-USER> (describe 'test) 
COMMON-LISP-USER::TEST 
    [symbol] 

TEST names a special variable: 
    Value: 42 

TEST names a compiled function: 
    Lambda-list:() 
    Derived type: (FUNCTION NIL (VALUES NULL &OPTIONAL)) 
    Source form: 
    (LAMBDA() 
     (DECLARE (MUFFLE-CONDITIONS COMPILER-NOTE)) 
     (PROGN 
     (SB-INT:NAMED-LAMBDA TEST 
      NIL 
     (BLOCK TEST)))) 

TEST names the standard-class #<STANDARD-CLASS TEST>: 
    Direct superclasses: STANDARD-OBJECT 
    No subclasses. 
    Not yet finalized. 
    No direct slots. 

; No value 

CL-USER> (make-instance 'test) 
#<TEST {1005B1D601}> 
CL-USER> (test) 
NIL 
CL-USER> test 
42 
CL-USER> 
+0

Bạn có thể giải thích lý do tại sao bạn cho rằng "nó giúp mọi người dễ dàng hơn" không? Tôi đã không viết nhiều Đề án, nhưng tôi đã viết một số tiền hợp lý của Python, và không bao giờ có một vấn đề với muốn cung cấp cho một lớp, dụ, và/hoặc phương pháp cùng tên. Cho rằng vấn đề, ngay cả trong Common Lisp nơi tôi có thể tái sử dụng tên như thế này, tôi không nghĩ rằng tôi đã từng có. Các trường hợp có xu hướng là danh từ, hàm có xu hướng là động từ, vv – Ken

+1

@Ken: Tôi thường viết những thứ như '(defun foo (danh sách) (danh sách (danh sách thanh)))' trong CL, không hoạt động với single không gian tên. Phải đặt tên cho các đối số của tôi những thứ như 'lyst' hoặc' lst' trong Scheme khiến tôi hơi điên. – Pillsy

+2

Pillsy: Đúng vậy. Sau đó, một lần nữa, gọi đối số 'danh sách' sẽ khiến tôi hơi điên, vì nó không mang tính mô tả. Tôi gọi nó là 'source' hoặc' target' hoặc 'haystack' hoặc' words' cho biết mục đích của danh sách là gì. Nếu tôi gọi params theo kiểu của chúng, 90% số arg của tôi sẽ là 'list'. :-) – Ken

7

Mặc dù có thể có rất nhiều lý lẽ mỗi chiều về mặt lý thuyết, tôi muốn đặt cược rằng nó phần lớn là triết học trong xứ. Đề án, một Lisp-1, thích sự thanh lịch hơn tính thực tiễn, và đã chọn cú pháp define tương tự cho các biến và hàm, làm cho một không gian tên duy nhất cảm thấy tự nhiên (và khuyến khích một kiểu lập trình chức năng). Lisp thường có xu hướng thích tính thực tiễn và sức mạnh hơn sự tao nhã, và là một nỗ lực trong việc xây dựng sự đồng thuận, vì vậy nhìn thấy một giải pháp hai không gian tên hiện có được chấp nhận rộng rãi và hoạt động tốt, chấp nhận nó.

Trên thực tế, tuy nhiên, nó chủ yếu có nghĩa là ba điều:

  • Trong Common Lisp (và khác Lisp-2 của), bạn phải sử dụng funcall rất nhiều
  • Trong Scheme (và khác Lisp-1), bạn phải cẩn thận không ghi đè tên chức năng cần thiết với các biến; ví dụ. đối số chức năng như lst thay vì list
  • Trên Internet, sẽ có lập luận

Đây là một yếu tố quan trọng trong lý do tại sao một số người thích một Lisp khác, tuy nhiên.

+5

Kết quả của sự khác biệt đi sâu hơn so với chỉ sử dụng 'funcall' hoặc tránh xung đột tên: sử dụng các hàm bậc cao hơn trong Đề án là tự nhiên hơn, do đó thành ngữ hơn, do đó trình biên dịch sẽ làm việc chăm chỉ để tối ưu hóa nó. Tuy nhiên, trong CL, nếu bạn đang sử dụng 'defvar' để định nghĩa một biến, và sau đó' funcall' nó, thì trình biên dịch rất có khả năng biên dịch nó thành mã chậm hơn nhiều so với sử dụng định nghĩa hàm. Điều này tương tự như CLers thích các cấu trúc vòng lặp và các lược đồ thích các cuộc gọi đuôi hơn. Nhưng tất nhiên điểm thứ ba của bạn là quan trọng nhất ... –

+0

Đó là sự thật, và một phần của ý tôi là "khuyến khích một phong cách lập trình chức năng" --- cảm ơn vì đã làm cho nó rõ ràng hơn. – JasonFruit

0

Ngoài các vấn đề khác được đề cập ở trên, có một không gian tên riêng cho các chức năng làm cho các macro không hợp vệ sinh của CL ít có khả năng cắn người dùng macro hơn. Trong CL, một tên bị ràng buộc tại điểm gọi xuất hiện trong khi mở rộng macro sẽ có định nghĩa được sử dụng tại điểm gọi, không phải là định nghĩa được sử dụng khi macro được xác định. Vì vậy, trong một phiên bản CL của Lisp-1, nếu macro mở rộng đến một cuộc gọi trên hàm LIST, và LIST được định nghĩa là một biến tại điểm mà macro được gọi, macro sẽ bị trục trặc. (Lưu ý rằng gensyms không giải quyết vấn đề này, không giống như các vấn đề nghịch đảo mà họ làm giải quyết.)

Điều này không xảy ra trong Đề án bởi vì các lược đồ mặc định là hợp vệ sinh: tất cả các tên được sử dụng trong việc mở rộng macro đều có nghĩa là macro được xác định, không phải nơi được sử dụng.

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