[英]clojure dynamic binding, read-string and eval Unable to resolve symbol
[英]Clojure evaluating string variable as a symbol, is this use of read-string okay?
我可以使用memfn創建調用Java函數的clojure函數。
(macroexpand '(memfn startsWith prefix))
=> (fn* ([target2780 prefix] (. target2780 (startsWith prefix))))
((memfn startsWith prefix) "abc" "a")
=> true
memfn
要求函數名稱為符號。 我想知道是否可以編寫一個宏來調用名稱作為字符串提供的任意方法。 也就是說,我希望能夠調用以下內容:
(def fn-name "startsWith")
=> #'user/fn-name
(macroexpand '(memfn' fn-name "prefix"))
=> (fn* ([target2780 prefix] (. target2780 (startsWith prefix))))
((memfn fn-name "prefix") "abc" "a")
=> true
我能想到的唯一方法是使用read-string
。
(defmacro memfn' [fn-name arg-name]
`(memfn ~(read-string fn-name) ~arg-name))
編輯:使用讀取字符串和eval的版本實際上以我想要的方式工作。
(defn memfn' [fn-name arg-name]
(eval (read-string (str "(memfn " fn-name " " arg-name ")"))))
我是否缺少基本的宏構建工具,無法將符號引用的字符串轉換為文字,而不必像read-string
那樣潛在地執行代碼?
感謝您的任何想法!
無論有沒有讀取字符串,都無法做到這一點。 您提出的解決方案不起作用。 您真正要做出的區分不是字符串和符號之間的區別,而是運行時數據和編譯時文字之間的區別。 宏不會評估接收到的參數,因此即使fn-name
是值為"startsWith"
的var的名稱, memfn
(或您的memfn'
宏)也只會看到fn-name
。
如果你有興趣在調用Java方法只有這樣,你可以依靠的java.lang.reflect.Method和invoke方法。
這樣的事情應該適用於無參數方法,並且不需要宏。
(defn memfn' [m]
(fn [o] (.invoke (.getMethod (-> o .getClass) m nil) o nil)))
((memfn' "length") "clojure")
;=>7
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.