2011-11-10 42 views
7

Câu hỏi này xuất phát hoàn toàn từ "tinh thần trí tuệ" và có lẽ không có giá trị thực tiễn.Hằng số thời gian biên dịch Clojure

Nếu tôi xác định giá trị trong Clojure bằng cách sử dụng def, trình biên dịch có thể được kích hoạt để đánh giá nó tại thời gian biên dịch hay không và chờ cho đến khi chạy đúng thời gian?

(def the-answer 42) 

(+ the-answer 1) 

Tôi đoán tôi có thể định nghĩa một macro, nhưng cú pháp gọi điện thoại trở thành loại lúng túng:

(defmacro the-answer [] 42) 

(+ (the-answer) 1) 

cũng trình này, nhưng vẫn còn xấu xí:

(+ `~the-answer 1) 

Tôi cũng hiểu (hoặc tin rằng) Clojure đánh giá các biểu thức liên tục tại thời gian biên dịch:

(def milliseconds-per-day (* 24 60 60 1000)) 

Tôi chỉ học Common Lisp, nhưng sự hiểu biết của tôi là Common Lisp hỗ trợ người dùng định nghĩa macro đọc, vì vậy bạn có thể định nghĩa một macro đọc (cái gì đó như #$) mà đánh giá các biểu tượng sau tại thời gian biên dịch:

(+ #$the-answer 1) 

Nhân tiện, cú pháp đó không "đẹp hơn" so với cuộc gọi macro.

Làm cách nào để làm cho Clojure đánh giá các biến cố định tại thời gian biên dịch và thay thế tham chiếu bằng giá trị thực tế? Liệu nó đã làm như vậy?

Trước khi bất cứ ai bắt đầu trích dẫn Luật Knuth ("tối ưu hóa sớm là gốc rễ của tất cả điều ác"), tôi hỏi câu hỏi này để hiểu rõ hơn về nội bộ của trình biên dịch Clojure.

+0

Đó không phải là những gì được thực hiện. Giáo hoàng là nói một cách hờ hững hoặc giáo điều. –

+0

Vâng, tôi đã xóa nó. – Ralph

Trả lời

11

Từ Clojure 1.3 docs

== 2.14 ^: const defs ==

^: const cho phép bạn đặt tên cho giá trị nguyên thủy với tài liệu tham khảo nhanh hơn.

(def hằng {: pi 3.14: Địa chỉ e 2,71}) ​​

(def ^: const pi (: hằng số pi)) (def ^: const e (: e hằng))

Các overhead tra cứu: e và: pi trong bản đồ xảy ra tại thời gian biên dịch , vì (: hằng số pi) và (: hằng số) được đánh giá khi các biểu mẫu lỗi gốc của chúng được đánh giá là .

5

Một trong những ứng dụng chính của macro là di chuyển tính toán để biên dịch thời gian nên nó chỉ được thực hiện một lần. Với ý nghĩ này, ý kiến ​​của tôi là các macro là công cụ chính xác cho này và tập hợp thêm () trông giống như tôi thực sự giúp làm cho các bộ phận đặc biệt trông đặc biệt.

+0

Đó là một câu trả lời hợp lý, và tôi cũng nghĩ như vậy. Cú pháp đẹp hơn '% câu trả lời thay thế. – Ralph

2

`~foo theo nghĩa đen giống hệt với foo trong mọi trường hợp - bất kỳ điều gì bạn cho rằng bạn đang thoát ra trước đây là ảo tưởng.

Tôi nghĩ rằng :const có lẽ là câu trả lời đúng, nhưng bạn cũng có thể sử dụng ký hiệu-macro từ clojure.tools.macro - nó có symbol-macroletdefsymbolmacro/with-symbol-macros cho mục đích này (cũng như các mục đích sử dụng khác).

+0

Tôi không nhận ra rằng về '~ foo. Cảm ơn. Khi tôi nghĩ nhiều hơn về vấn đề này, '^: const' có vẻ như đúng, nhưng ** chỉ dành cho nguyên thủy ** (không bao gồm các thể hiện' String'). Vấn đề với chuỗi là việc sử dụng macro hoặc const có thể dẫn đến việc so sánh thời gian chạy của nội dung 'Chuỗi' và không phải là địa chỉ. Nếu lý do để làm điều này là để thực hiện, đó là một mất mát. – Ralph

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