2011-10-16 30 views
9

CHỈNH SỬA: Tôi đã thay đổi mã mẫu sau câu trả lời đầu tiên vì tôi đã đưa ra một phiên bản đơn giản yêu cầu cùng một câu hỏi.Phạm vi Lisp chung (động và từ vựng)

Tôi hiện đang học thuộc tính phạm vi của Common Lisp. Sau khi tôi nghĩ rằng tôi đã có một sự hiểu biết vững chắc, tôi quyết định viết một số ví dụ mà tôi có thể dự đoán kết quả của, nhưng dường như tôi đã sai. Tôi có ba câu hỏi, mỗi người có liên quan đến một ví dụ dưới đây:

Ví dụ 1:

(defmethod fun1 (x) 
    (print x) 
    (fun2)) 

(defmethod fun2() 
    (print x)) 

(fun1 5) 

Output:

5 
*** - EVAL: variable X has no value 

Câu hỏi: Đây có ý nghĩa. x là phạm vi tĩnh và fun2 không có cách nào để tìm giá trị của x mà không có nó được truyền một cách rõ ràng.

Ví dụ 2:

(defvar x 100) 

(defmethod fun1 (x) 
    (print x) 
    (fun2)) 

(defmethod fun2() 
    (print x)) 

(fun1 5) 

Output:

5 
5 

Câu hỏi: Tôi không hiểu tại sao x là đột nhiên nhìn thấy fun2 với giá trị fun1 đó đã cho nó, thay vì có một giá trị của 100 ...

Ví dụ 3:

(setf x 100) 

(defmethod fun1 (x) 
    (print x) 
    (fun2)) 

(defmethod fun2() 
    (print x)) 

(fun1 5) 

Output:

5 
100 

Câu hỏi: Tôi có nên bỏ qua những kết quả kể từ khi gọi setf trên một biến chưa được khai báo là dường như không xác định? Điều này xảy ra là những gì tôi mong chờ trong ví dụ thứ hai của tôi ...

Bất kỳ cái nhìn sâu sắc sẽ được đánh giá rất ...

+0

Dưới đây là lời giải thích ngây thơ của tôi sau khi chơi xung quanh một chút ... cho tôi biết nếu tôi gần .. Exmaple 1: không cần giải thích Ví dụ 2: khai báo x là một biến động gây ra tất cả các trường hợp x được tra cứu tại thời gian chạy trên ngăn biến động, điều này sẽ khiến fun2 kế thừa giá trị của x từ fun1, mặc dù không phải là biến động. Ví dụ3: không có ý tưởng ... Tôi đoán không xác định của nó –

+0

* Việc đặt câu hỏi * là tốt. * Các câu hỏi bắt đầu * là xấu ** ** –

+0

Thay vì DEFMETHOD sử dụng DEFUN. DEFMETHOD không cần thiết trong các ví dụ này. DEFUN tạo ra một hàm đơn giản. DEFMETHOD dành cho các chức năng chung, nơi bạn cần một số điều phối. –

Trả lời

18

Ảnh hưởng của thiết lập một biến không xác định sử dụng SETF là undefined trong ANSI Common Lisp.

DEFVAR sẽ xác định biến đặc biệt. Tuyên bố này là toàn cầu và cũng có hiệu lực đối với các ràng buộc LET. Đó là lý do mà theo quy ước, các biến này được viết là *foo*. Nếu bạn đã từng định nghĩa X với DEFVAR, nó được khai báo đặc biệt và không có cách nào để khai báo nó theo từ vựng sau này.

LET theo mặc định cung cấp các biến từ vựng cục bộ. Nếu biến đã được khai báo đặc biệt (ví dụ vì một DEFVAR), thì nó chỉ tạo ra một ràng buộc động mới cục bộ.

Cập nhật

  • Ví dụ 1.

Không có gì để xem.

  • Ví dụ 2

X đã được tuyên bố đặc biệt. Tất cả các công dụng của biến X bây giờ sử dụng ràng buộc động. Khi gọi hàm, bạn liên kết X đến 5. Tự động. Các chức năng khác hiện có thể truy cập vào liên kết động này và nhận giá trị đó.

  • Ví dụ 3

Đây là hành vi không xác định trong Common Lisp. Bạn đang đặt biến chưa khai báo. Điều gì xảy ra sau đó là thực hiện phụ thuộc. Việc thực hiện của bạn (hầu hết làm một cái gì đó tương tự) đặt giá trị biểu tượng của X thành 100. Trong FUN1, X bị ràng buộc bằng từ vựng. Trong FUN2 đánh giá X truy xuất giá trị ký hiệu (hoặc có thể với giá trị ràng buộc động) của X.

Ví dụ về việc triển khai thực hiện một điều gì đó khác: thực hiện CMUCL cũng sẽ khai báo X trong ví dụ 3 theo mặc định là đặc biệt. Đặt một biến không xác định cũng khai báo nó đặc biệt.

LƯU Ý

Trong tiêu chuẩn di động phù hợp đang Common Lisp các biến toàn cầu được định nghĩa với DEFVAR và DEFPARAMETER. Cả hai tuyên bố các biến này là đặc biệt. TẤT CẢ việc sử dụng các biến này hiện nay liên quan đến ràng buộc động.

Hãy nhớ rằng:

((lambda (x) 
    (sin x)) 
10) 

về cơ bản là giống như

(let ((x 10)) 
    (sin x)) 

Có nghĩa là gán biến trong bindings LET và bindings biến trong các cuộc gọi chức năng đang làm việc cùng một cách. Nếu X có thể đã được tuyên bố đặc biệt ở một số nơi trước đó, cả hai sẽ liên quan đến năng động ràng buộc.

Điều này được quy định trong tiêu chuẩn Common Lisp. Xem ví dụ giải thích cho SPECIAL declaration.

+0

Tôi đã cập nhật bài đăng gốc của mình với các ví dụ và câu hỏi chính xác hơn phản ánh những gì tôi gặp khó khăn khi hiểu. Cụ thể, hành vi được thể hiện trong ví dụ thứ hai của tôi khi so sánh với ví dụ đầu tiên của tôi –

+0

Cảm ơn bạn đã làm rõ! Tôi không nghĩ rằng tôi đã mong đợi các giá trị tham số của các chức năng được thực hiện giống như các biến miễn phí bình thường ... nhưng tôi cho rằng mọi đề cập đều được xử lý như nhau. –

+1

@ antman8969: sử dụng biến là giống nhau ở mọi nơi. Một chút ngạc nhiên là các tham số chức năng cũng có thể bị ràng buộc động và chúng bị ảnh hưởng bởi định nghĩa các biến với DEFVAR. –

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