2016-01-05 13 views
6

Tôi đang đọc một số mã Clojure tại thời điểm này có một loạt các giá trị chưa được khởi tạo là nil cho một giá trị số trong một bản ghi được truyền đi xung quanh.Có một sự thay thế thành ngữ nào để nil-punning trong Clojure không?

Bây giờ rất nhiều thư viện Clojure treat this as idiomatic. Có nghĩa là nó là một quy ước được chấp nhận.

Nhưng nó cũng dẫn đến NullPointerException, bởi vì không phải tất cả các chức năng chính của Clojure đều có thể xử lý nil làm đầu vào. (Họ cũng không nên).

Các ngôn ngữ khác có khái niệm Maybe hoặc Option để ủy quyền giá trị trong trường hợp giá trị rỗng, như một cách để giảm thiểu nguy cơ NullPointerException. Điều này có thể có trong Clojure - but not very common.

Bạn có thể thực hiện một số thủ thuật với fnil nhưng không giải quyết được mọi sự cố.

Một phương án khác đơn giản là đặt giá trị chưa được khởi tạo thành một biểu tượng như :empty-value để buộc người dùng xử lý tình huống này một cách rõ ràng trong tất cả mã xử lý. Nhưng đây không phải là bước tiến lớn từ nil - bởi vì bạn không thực sự khám phá tất cả các kịch bản (trong mã của người khác) cho đến khi chạy.

Câu hỏi của tôi là: Có một lựa chọn thành ngữ nào để nil-punning trong Clojure không?

Trả lời

5

Không chắc chắn nếu bạn đã đọc này lispcast post trên nil-punning, nhưng tôi nghĩ rằng nó làm một trường hợp khá tốt cho lý do tại sao nó là thành ngữ và bao gồm cân nhắc quan trọng khác nhau mà tôi không thấy đề cập trong những SO câu hỏi khác.

Về cơ bản, nilhạng nhất điều trong clojure. Mặc dù ý nghĩa thông thường vốn có của nó, nó một giá trị thích hợp và có thể được xử lý như vậy trong nhiều ngữ cảnh và theo cách phụ thuộc vào ngữ cảnh. Điều này làm cho nó linh hoạt và mạnh mẽ hơn null bằng ngôn ngữ máy chủ.

Ví dụ, một cái gì đó như thế này thậm chí sẽ không biên dịch trong java:

if(null) { 
.... 
} 

đâu như trong clojure, (if nil ...) sẽ chỉ làm việc tốt. Vì vậy, có rất nhiều tình huống mà bạn có thể sử dụng số: an toàn. Tôi chưa thấy một codebase java không phải là được rải rác với mã như if(foo != null) { ... ở khắp mọi nơi. Có lẽ Optional của java 8 sẽ thay đổi điều này.

Tôi nghĩ rằng nơi bạn có thể gặp sự cố khá dễ dàng là trong các tình huống tương tác java nơi bạn đang xử lý thực tế null s. Thư viện trình bao bọc clojure tốt cũng có thể giúp bạn che giấu điều này trong nhiều trường hợp, và một lý do chính đáng của nó là thích một liên kết trực tiếp trên java nếu có thể.

Trong điều kiện này, bạn có thể muốn xem xét lại việc chống lại hiện tại này. Nhưng kể từ khi bạn đang hỏi về lựa chọn thay thế, đây là một trong những tôi nghĩ là tuyệt vời: prismatic's schema. Giản đồ có lược đồ Maybe (và nhiều lược đồ hữu ích khác), và nó hoạt động khá độc đáo trong nhiều tình huống. Thư viện khá phổ biến và tôi đã sử dụng nó với thành công.FWIW, nó được đề nghị trong cuốn sách clojure applied gần đây.

1

Có cách thay thế thành ngữ nào để không phô trương trong Clojure không?

No. leeor giải thích, nil-punning là thành ngữ. Nhưng nó không phổ biến như trong Common Lisp, nơi (tôi được kể) một danh sách trống tương đương với số không.

Clojure được sử dụng để làm việc theo cách này, nhưng các hàm CL xử lý các danh sách tương ứng với các hàm Clojure xử lý các chuỗi nói chung. Và những trình tự này có thể là lười biếng, do đó, có một phí bảo hiểm về chuỗi thống nhất lười biếng với những người khác, để bất kỳ sự lười biếng có thể được bảo tồn. Tôi nghĩ sự tiến hóa này đã xảy ra với Clojure 1.2. Giàu mô tả chi tiết here.

Nếu bạn muốn tùy chọn/có thể loại, hãy xem thư viện core.typed. Ngược lại với Prismatic Schema, nó hoạt động ở thời gian biên dịch.

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