2010-10-04 28 views
12

defrecord trong clojure cho phép xác định vùng chứa dữ liệu đơn giản với các trường tùy chỉnh.Macro được đề xuất để thêm chức năng vào hàm tạo dấu gạch ngang của Clojure?

ví dụ:

user=> (defrecord Book [author title ISBN]) 
user.Book 

Các nhà xây dựng tối thiểu mà kết quả chỉ mất đối số vị trí không có chức năng bổ sung như mặc định của các trường, xác nhận hiện trường, vv

user=> (Book. "J.R.R Tolkien" "The Lord of the Rings" 9780618517657) 
#:user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657} 

Nó luôn luôn có thể viết các chức năng gói các constructor mặc định để có được ngữ nghĩa xây dựng phức tạp hơn - sử dụng đối số từ khóa, cung cấp mặc định và v.v.

Điều này có vẻ giống như kịch bản lý tưởng cho macro để cung cấp ngữ nghĩa mở rộng. Macro nào mà mọi người đã viết và/hoặc đề xuất xây dựng hơn defrecord?

+0

Tôi nên chỉ ra rằng defrecord có nhiều thứ cho nó về cách nó hoạt động với hệ sinh thái Clojure/Java, "các thùng chứa dữ liệu đơn giản" ở trên không có nghĩa là thô sơ, hoàn toàn ngược lại. –

+0

Nên nói rằng từ clojure 1.3.0, bạn có thể làm '(map-> Book {: author" JRR Tolkien ",: title" Chúa tể của những chiếc nhẫn ",: ISBN 9780618517657)' hoặc '# user.Book {: tác giả "JRR Tolkien",: tiêu đề "Chúa tể của những chiếc nhẫn",: ISBN 9780618517657} ' – Claude

+0

Để tìm tài liệu về các tính năng được ghi chú bởi Claude, hãy xem: http://dev.clojure.org/display/design/defrecord+ cải tiến –

Trả lời

9

Ví dụ về hỗ trợ cho các chức năng ghi lại constructor đầy đủ và một phần và hỗ trợ cho các hình thức in ấn và pprint eval-thể:

David là một đồng nghiệp của tôi và chúng tôi đang sử dụng defrecord2 này rộng rãi trong dự án của chúng tôi. Tôi nghĩ rằng một cái gì đó như thế này thực sự nên là một phần của lõi Clojure (chi tiết có thể khác nhau đáng kể của khóa học).

Những điều chúng tôi nhận thấy là quan trọng là:

  • Có khả năng xây dựng một kỷ lục với tên (có thể là một phần) các thông số: (mới-foo {: 1})
  • Khả năng xây dựng một bản ghi bằng cách sao chép một bản ghi hiện có và thực hiện các sửa đổi: (new-foo old-foo {: a 10})
  • Xác nhận trường - nếu bạn vượt qua một trường ngoài các trường bản ghi đã khai báo, hãy báo lỗi. Tất nhiên, điều này thực sự là hợp pháp và có khả năng hữu ích, do đó, có nhiều cách để làm cho nó tùy chọn. Vì nó sẽ rất hiếm trong việc sử dụng của chúng tôi, nó có nhiều khả năng là một lỗi.
  • Giá trị mặc định - những giá trị này sẽ rất hữu ích nhưng chúng tôi chưa triển khai. Chas Emerick đã viết về việc thêm hỗ trợ cho các giá trị mặc định tại đây: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
  • Hỗ trợ in và in - chúng tôi thấy rất hữu ích để có bản ghi in và in dưới dạng có thể quay trở lại bản ghi gốc. Ví dụ, điều này cho phép bạn chạy thử nghiệm, vuốt đầu ra thực tế, xác minh nó và sử dụng nó như đầu ra mong đợi. Hoặc để trượt đầu ra từ một dấu vết gỡ lỗi và nhận được một hình thức thực sự eval.
+0

Chắc chắn đồng ý với một trường không được xác định có thể là một lỗi (nhưng hữu ích khi cố ý). Là một trong những có lẽ biết lĩnh vực mở rộng là cố ý nó nên có lẽ có một chức năng khác nhau và thẳng assoc ném một lỗi. Tôi cũng tự hỏi liệu siêu dữ liệu trên một bản ghi mở rộng có hữu ích hay không. –

4

Here is one xác định bản ghi có giá trị mặc định và bất biến. Nó tạo ra một ctor có thể lấy từ khóa args để thiết lập các giá trị của các trường.

(defconstrainedrecord Foo [a 1 b 2] 
    [(every? number? [a b])]) 

(new-Foo) 
;=> #user.Foo{:a 1, :b 2} 

(new-Foo :a 42) 
; #user.Foo{:a 42, :b 2} 

Và như tôi đã nói ...bất biến:

(new-Foo :a "bad") 
; AssertionError 

Nhưng chúng chỉ có ý nghĩa trong ngữ cảnh Trammel.

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