Viết tắt hàm ẩn danh


85

Có điều gì đó tôi không hiểu về các hàm ẩn danh sử dụng ký hiệu ngắn gọn # (..)

Các hoạt động sau:

REPL>  ((fn [s] s) "Eh")
"Eh"

Nhưng điều này không:

REPL>  (#(%) "Eh")

Những công việc này:

REPL> (#(str %) "Eh")
"Eh"

Điều tôi không hiểu là tại sao (# (%) "Eh") không hoạt động và đồng thời tôi không cần sử dụng str trong ((fn [s] s) "Eh")

Cả hai đều là các hàm ẩn danh và cả hai đều lấy, ở đây, một tham số. Tại sao ký hiệu viết tắt cần một hàm trong khi ký hiệu khác thì không?

Câu trả lời:


126
#(...)

là viết tắt của

(fn [arg1 arg2 ...] (...))

(trong đó số lượng argN phụ thuộc vào bạn có bao nhiêu% N trong cơ thể). Vì vậy, khi bạn viết:

#(%)

nó được dịch thành:

(fn [arg1] (arg1))

Lưu ý rằng chức năng này khác với chức năng ẩn danh đầu tiên của bạn, giống như:

(fn [arg1] arg1)

Phiên bản của bạn trả về arg1 dưới dạng một giá trị, phiên bản đến từ việc mở rộng tốc độ viết tắt cố gắng gọi nó là một hàm. Bạn gặp lỗi vì một chuỗi không phải là một hàm hợp lệ.

Vì tốc ký cung cấp một tập hợp các dấu ngoặc đơn quanh phần thân, nó chỉ có thể được sử dụng để thực hiện một lệnh gọi hàm đơn hoặc dạng đặc biệt.


64

Như các câu trả lời khác đã được chỉ ra rất độc đáo, câu trả lời #(%)bạn đã đăng thực sự mở rộng thành một cái gì đó giống như (fn [arg1] (arg1)), không giống chút nào (fn [arg1] arg1).

@John Flatness đã chỉ ra rằng bạn chỉ có thể sử dụng identity, nhưng nếu bạn đang tìm cách viết identitybằng #(...)macro điều phối, bạn có thể làm như sau:

#(-> %)

Bằng cách kết hợp #(...)macro điều phối với macro phân ->luồng, nó sẽ được mở rộng thành một cái gì đó giống như (fn [arg1] (-> arg1)), mở rộng trở lại (fn [arg1] arg1), đúng như bạn muốn. Tôi cũng thấy tổ hợp macro ->#(...)macro hữu ích cho việc viết các hàm đơn giản trả về vectơ, ví dụ:

#(-> [%2 %1])

20

Khi sử dụng #(...), bạn có thể tưởng tượng rằng thay vào đó bạn đang viết (fn [args] (...)), bao gồm các dấu ngoặc đơn mà bạn bắt đầu ngay sau bảng Anh.

Vì vậy, ví dụ không hoạt động của bạn chuyển đổi thành:

((fn [s] (s)) "Eh")

điều này rõ ràng không hoạt động vì bạn đang cố gọi chuỗi là "Eh". Ví dụ của bạn với strcác hoạt động bởi vì bây giờ chức năng của bạn là (str s)thay vì (s). (identity s)sẽ là tương tự gần hơn với ví dụ đầu tiên của bạn, vì nó sẽ không bắt buộc phải str.

Nó có ý nghĩa nếu bạn nghĩ về nó, vì ngoài ví dụ hoàn toàn tối thiểu này, mọi hàm ẩn danh sẽ gọi một cái gì đó , vì vậy sẽ hơi ngu ngốc nếu yêu cầu một bộ parens lồng nhau khác để thực sự gọi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.