Vâng, var cũng tương tự như một con trỏ C. Đây là tài liệu kém.
Giả sử bạn định nghĩa fred
như sau:
(defn fred [x] (+ x 1))
Thực tế, có 3 điều ở đây. Trước hết, fred
là một biểu tượng. Có sự khác biệt giữa biểu tượng fred
(không có dấu ngoặc kép) và từ khóa :fred
(được đánh dấu bằng số :
char hàng đầu) và chuỗi "fred"
(được đánh dấu bằng dấu ngoặc kép ở cả hai đầu). Để Clojure, mỗi người trong số họ bao gồm 4 ký tự; tức là không phải dấu hai chấm của từ khóa lẫn dấu ngoặc kép của chuỗi được bao gồm trong độ dài hoặc thành phần của chúng:
> (name 'fred)
"fred"
> (name :fred)
"fred"
> (name "fred")
"fred"
Sự khác biệt duy nhất là cách chúng được diễn giải. Một chuỗi có nghĩa là đại diện cho dữ liệu người dùng của bất kỳ loại nào. Từ khóa có nghĩa là đại diện cho thông tin kiểm soát cho chương trình, dưới dạng "số ma thuật" như 1 = bên trái, 2 = phải, chúng tôi chỉ sử dụng từ khóa :left
và :right
.
Biểu tượng này có nghĩa là điểm đến điều gì đó, giống như trong Java hoặc C. Nếu chúng ta nói
(let [x 1
y (+ x 1) ]
(println y))
;=> 2
sau đó x
điểm với giá trị 1, y
điểm với giá trị 2, và chúng ta thấy kết quả in ra.
dạng (def ...)
giới thiệu một số vô hình yếu tố thứ ba, var
. Vì vậy, nếu chúng tôi nói
(def wilma 3)
chúng tôi hiện có 3 đối tượng để xem xét. wilma
là một biểu tượng, trỏ đến số var
, lần lượt trỏ đến giá trị 3
. Khi chương trình của chúng tôi gặp biểu tượng wilma
, đó là được đánh giá để tìm số var
. Tương tự như vậy, var là được đánh giá để mang lại giá trị 3. Vì vậy, nó giống như một con trỏ 2 cấp của con trỏ trong C.Vì cả hai biểu tượng và var được "tự động đánh giá", điều này xảy ra tự động và vô hình và bạn không phải suy nghĩ về var (thực sự, hầu hết mọi người không thực sự biết bước giữa vô hình thậm chí tồn tại).
Đối với chức năng của chúng tôi fred
ở trên, một tình huống tương tự tồn tại, ngoại trừ điểm var cho hàm ẩn danh (fn [x] (+ x 1))
thay vì giá trị 3
như với wilma
.
Chúng tôi có thể "ngắn mạch" tự động đánh giá của var như:
> (var wilma)
#'clj.core/wilma
hoặc
> #'wilma
#'clj.core/wilma
nơi người đọc vĩ mô #'
(lb-quote) là một cách viết tắt của gọi số (var ...)
biểu mẫu đặc biệt. Hãy nhớ rằng một dạng đặc biệt như var
là trình biên dịch được tích hợp như 'if' hoặc 'def' và không giống như một hàm thông thường. Biểu mẫu đặc biệt var
trả về đối tượng var
được gắn vào biểu tượng wilma
. REPL clojure in các đối tượng var
sử dụng cùng một cách viết tắt, vì vậy cả hai kết quả trông giống nhau.
Một khi chúng ta có đối tượng var, tự động đánh giá bị vô hiệu hóa:
> (println (var wilma))
#'clj.core/wilma
Nếu chúng ta muốn để có được giá trị mà wilma
điểm đến, chúng ta cần phải sử dụng var-get
:
> (var-get (var wilma))
3
> (var-get #'wilma)
3
Điều tương tự cũng hoạt động đối với fred:
> (var-get #'fred)
#object[clj.core$fred 0x599adf07 "[email protected]"]
> (var-get (var fred))
#object[clj.core$fred 0x599adf07 "[email protected]"]
nơi #object[clj.core$fred ...]
công cụ là cách của Clojure đại diện cho một đối tượng chức năng như một chuỗi.
Đối với máy chủ web, nó có thể thông qua chức năng var?
hoặc ngược lại nếu giá trị được cung cấp là hàm xử lý hoặc var trỏ đến hàm điều khiển.
Nếu bạn gõ một cái gì đó như:
(jetty/run-jetty handler)
kép tự động đánh giá sẽ mang lại đối tượng chức năng xử lý, mà được chuyển cho run-jetty
. Nếu, thay vào đó, bạn gõ:
(jetty/run-jetty (var handler))
thì var
mà chỉ vào đối tượng chức năng xử lý sẽ được chuyển đến run-jetty
. Sau đó, run-jetty
sẽ phải sử dụng tuyên bố if
hoặc tương đương để xác định nội dung đã nhận và gọi (var-get ...)
nếu đã nhận được var
thay vì chức năng. Do đó, mỗi lần thông qua (var-get ...)
sẽ trả về đối tượng mà tại đó var
hiện đang trỏ. Vì vậy, các hoạt động var
giống như một con trỏ toàn cầu trong C, hoặc một biến "tham chiếu" toàn cầu trong Java.
Nếu bạn vượt qua một đối tượng chức năng để run-jetty
, nó tiết kiệm một "con trỏ địa phương" cho đối tượng chức năng và không có cách nào cho thế giới bên ngoài để thay đổi những gì con trỏ địa phương đề cập đến.
Bạn có thể tìm thêm chi tiết ở đây: