2010-09-07 22 views
6

Trong một số triển khai của Common LISP chúng ta có thể nói rằng đối với các biểu thức sau đâyTrong clojure, là (= 'a' a) đề cập đến 'cùng một nguyên tử'?

(eq 'a 'a) 

true'a'a là "cùng một nguyên tử".

Điều này có thể phụ thuộc vào việc triển khai thực hiện, nhưng dường như cụm từ (được sử dụng trong sách dạy học LISP phổ biến) giả định rằng các nguyên tử có cùng giá trị được lưu trữ trong cùng một vị trí trong bộ nhớ.

Trong Java, hai chuỗi nội bộ có cùng giá trị được lưu trữ trong cùng một vị trí trong bộ nhớ.

Giờ Clojure trên JVM kế thừa di sản của Java, nhưng có đúng là nói rằng hai nguyên tử trong Clojure (trên JVM) có cùng giá trị là cùng một nguyên tử không? (Tức là cách làm việc cơ chế lưu trữ nguyên tử Clojure không?)

+2

Phương ngữ của Lisp thường? Cái gì đây? Phương ngữ nào? Việc triển khai Common Lisp thông thường đều thực hiện ANSI Common Lisp. Có tiếng địa phương của CL, nhưng đó không phải là quan trọng, vì hầu hết mọi người (bao gồm cả người dùng Lisp) có lẽ chưa bao giờ nghe nói về họ. Nhưng có rất nhiều phương ngữ của Lisp. - Bất kỳ Lisp thường sẽ trả về T cho (eq 'a' a). a cũng không phải là một nguyên tử, mà là một biểu tượng. Thuật ngữ 'nguyên tử' cũng không có ý nghĩa trong ngữ cảnh này. Trong lịch sử tất cả mọi thứ mà không phải là một tế bào cons là một nguyên tử. –

+0

"Trong Java, hai chuỗi có cùng giá trị được lưu trữ trong cùng một vị trí trong bộ nhớ." - chỉ khi cả hai thực tập. –

Trả lời

21

Thứ nhất, "nguyên tử" có ý nghĩa khác trong Clojure so với hầu hết các Lisps khác. Xem http://clojure.org/atoms

Clojure's = chức năng sử dụng giá trị dựa trên sự bình đẳng. Vì vậy, hai đối tượng có giá trị bằng nhau sẽ là = ngay cả khi chúng được lưu trữ ở các vị trí khác nhau trong bộ nhớ.

Để kiểm tra xem hai đối tượng có thực sự là cùng một đối tượng hay không, tại cùng một địa chỉ trong bộ nhớ, hãy sử dụng hàm identical?.

4

Tôi sẽ giải thích phần Common Lisp:

Trong Common Lisp (eq 'a' a) luôn trả về T.

Lý do: tại đọc thời gian, người đọc tra cứu a và cho cả hai a nó sẽ tra cứu cùng một biểu tượng a. Vì bất kỳ biểu tượng nào cũng là EQ, biểu thức sẽ trả về luôn luôn T.

Điều này đúng với hầu hết các loại đối tượng, nhưng có một vài ngoại lệ. Các số và ký tự, chẳng hạn, không phải là EQ cần thiết trong Common Lisp. Lý do cho điều đó là hiệu quả. Để so sánh chúng nếu chúng cùng một số hoặc cùng một ký tự thì có thể sử dụng hàm EQL.

6

Tôi nghĩ 'a' và 'sẽ là các đối tượng Java khác nhau dưới mui xe. Tôi tin rằng điều này khẳng định nghi ngờ rằng:

user> (def foo 5) 
#'user/foo 
user> (System/identityHashCode 'foo) 
578999228 
user> (System/identityHashCode 'foo) 
1724482638 

Nếu bạn nhìn vào việc thực hiện thực tế của Symbol trong Clojure, bạn sẽ thấy rằng một biểu tượng bao gồm một không gian tên và một tên và những Strings PHẢI được thực tập nội trú chuỗi. Phương thức Symbol.equals() dựa vào việc kiểm tra nhận dạng trên hai chuỗi đó, dựa vào thực thể chuỗi.

4

Để thêm vào câu trả lời của Alex và Stuart, Biểu tượng trong Clojure không thể được tạo thành identical? bất cứ khi nào chúng là = chủ yếu là vì chúng có thể mang siêu dữ liệu. Hai Biểu tượng có cùng các thành phần .name.namespace nhưng siêu dữ liệu khác nhau sẽ là = nhưng không phải là identical?.

Mọi thứ có thể được sắp xếp sao cho hai Biểu tượng có cùng siêu dữ liệu, không gian tên và tên sẽ luôn là identical?, nhưng đó là (1) hai rắc rối không thực sự đạt được (vì bạn vẫn có một số Biểu tượng = nhưng không phải là identical?), (2) trái với ý tưởng rằng các loại có thể mang siêu dữ liệu thường được so sánh với giá trị bình đẳng (mà siêu dữ liệu không đóng góp), trong khi con trỏ thực tế nên được dành riêng cho các tình huống đặc biệt (chủ yếu liên quan đến interop).

Lưu ý rằng Từ khóa Clojure là một loại riêng biệt mà = thực sự tương đương với identical?. (Vì vậy, rõ ràng họ không thể có siêu dữ liệu đính kèm.)

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