cuốn sách gpt4 ai đã làm

Tự động tạo các hàm hiệu suất cao trong clojure

In lại Tác giả: Taklimakan Thời gian cập nhật: 2023-11-03 04:05:30 25 4
mua khóa gpt4 Nike

Tôi đang cố gắng sử dụng Clojure để tạo động các hàm có thể áp dụng cho lượng lớn dữ liệu - tức là yêu cầu các hàm được biên dịch thành mã byte để thực thi nhanh, nhưng thông số kỹ thuật của chúng không được biết cho đến khi chạy.

Ví dụ: giả sử tôi sử dụng DSL đơn giản để chỉ định các chức năng, chẳng hạn như:

(def my-spec [:add [:multiply 2 :param0] 3])

Tôi muốn tạo một đặc tả biên dịch hàm:

(biên dịch-spec my-spec)

Sẽ trả về một hàm đã biên dịch với tham số x trả về 2x+3.

Cách tốt nhất để làm điều này trong Clojure là gì?

câu trả lời hay nhất

Hamza Yerlikaya đã đưa ra quan điểm quan trọng nhất, đó là mã Clojureluôn luônBiên dịch. Tôi vừa thêm hình minh họa và một số thông tin về một số thành quả dễ thực hiện cho nỗ lực tối ưu hóa của bạn.

Đầu tiên, điểm trên về việc mã Clojure luôn được biên dịch bao gồm các bao đóng được trả về bởi các hàm bậc cao hơn và chuyển fn/Đã gọi trên fn* đánh giá Chức năng đã tạo form và bất kỳ thứ gì khác có thể hoạt động như một hàm Clojure. Do đó, bạn không cần DSL riêng để mô tả các chức năng, chỉ cần sử dụng các hàm bậc cao hơn (và có thể cả macro):

(định nghĩa hàm tạo affine [ab]
(fn [x] (+ (* ax) b)))

((make-affine-function 31 47) 5)
;

Mọi thứ sẽ thú vị hơn nếu thông số kỹ thuật của bạn bao gồm thông tin về các loại tham số, vì bạn có thể quan tâm đến việc viết macro để tạo mã bằng cách sử dụng các gợi ý loại này. Ví dụ đơn giản nhất tôi có thể nghĩ đến là một biến thể của ví dụ trên:

(defmacro make-primitive-affine-function [tab]
(let [cast #(list (ký hiệu (tên t))) %)
x (gensym "x")]
`(fn [~x] (+ (* ~(cast a) ~(cast x)) ~(cast b)))))

((make-primitive-affine-function :int 31 47) 5)
;

sử dụng:int,:dài,:trôi nổi hoặc:gấp đôi(hoặc ký hiệu không đủ điều kiện về không gian tên của tên tương ứng) làm đối số đầu tiên để sử dụng thuật toán nguyên thủy không được đóng hộp phù hợp với loại đối số của bạn. Tùy thuộc vào chức năng của bạn đang làm gì, điều này có thể mang lại cho bạn hiệu suất tăng rất đáng kể.

Các loại lời nhắc khác thường được đưa ra bởi #^Thanh Foo Cú pháp được cung cấp (^Thanh Foo làm điều tương tự trong 1.2); nếu bạn muốn thêm chúng vào mã được tạo macro, hãy xem xét với-meta chức năng (bạn cần phải '{:tag Foo} hợp nhất vào biểu tượng đại diện cho chức năng của bạn hoặc cho phép Giới thiệu tham số chính thức của biến cục bộ nơi bạn muốn đặt gợi ý loại).


Ồ, và trong trường hợp bạn vẫn đang băn khoăn về cách thực hiện ý tưởng ban đầu của mình...

Bạn luôn có thể xây dựng các biểu thức Clojure để xác định hàm của mình-- (liệt kê 'fn ['x] (a-magic-function-to-generate-some-code some-args ...))-- và gọi kết quảđánh giá. Điều này sẽ cho phép bạn thực hiện những việc sau (sẽ đơn giản hơn nếu yêu cầu đặc tả chứa danh sách tham số, nhưng phiên bản ở đây giả định rằng bạn muốn trích xuất các tham số từ đặc tả, cả hai đều được gọi là thông sốFOO và sắp xếp theo từ điển):

(yêu cầu '[clojure.walk :as walk])

(defn biên dịch-spec [spec]
(hãy [params (nguyên tử #{})]
(đi bộ/đi trước
(fn [mục]
(if (và (ký hiệu? item) (.startsWith (tên mục) "param"))
(làm (hoán đổi! params conj mục)
mục)
mục))
thông số kỹ thuật)
(eval `(fn [~@(sort @params)] ~@spec))))

(def my-spec '[(+ (+(* 31 param0) 47)])

((biên dịch-spec my-spec) 5)
;

Trong hầu hết các trường hợp, không có lý do chính đáng để làm mọi việc theo cách này và thay vào đó nên tránh sử dụng các hàm và macro bậc cao hơn. Nhưng nếu bạn đang làm điều gì đó như lập trình tiến hóa, thì nó sẽ ở đó, mang lại sự linh hoạt nhất - kết quả vẫn là một hàm được biên dịch.

Về java - tạo động các hàm hiệu suất cao trong clojure, chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/2828239/

25 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress