作為我想做的一個最小的例子:
(defn mkfn [func]
(fn func [a] (print "I am a function")))
(mkfn 'x) ; => #function[user/mkfn/func--10871]
(type x)
(x)
最后兩個都導致:
Syntax error compiling at (conjure-log-12628.cljc:1:1).
Unable to resolve symbol: x in this context
我不確定為什么這不起作用,因為fn
將符號作為輸入并且'x
是符號。我也不確定如何完成這項任務。
對于這個問題:
user=> (def (eval 'y) 3)
Syntax error compiling def at (conjure-log-12628.cljc:1:1).
user=> (def 'y 3)
Syntax error compiling def at (conjure-log-12628.cljc:1:1).
First argument to def must be a Symbol
First argument to def must be a Symbol
user=> (type 'y)
clojure.lang.Symbol
其他不起作用的事情:
(defn mkfn [func]
(fn (sympol func) [a] (print "i am a function")))
(symbol "y") ; => y ; a symbol
(def (symbol "y") 3) ; => an err
uj5u.com熱心網友回復:
您可能需要一個宏。似乎您想通過提供的名稱呼叫該函式,因此您還必須替換fn
為defn
.
而且你必須小心許多引數,因為x
帶有引數向量的函式[a]
必須用一個引數呼叫,而不是像(x)
.
(defmacro mkfn [func]
`(defn ~func [~'a]
(print "I am a function")))
(mkfn x)
=> #'user/x
(x 1)
I am a function=> nil
還有其他方法,使用intern
,因此您可以完全避免撰寫宏:
(intern *ns* 'x (fn [a] (print "I am a function")))
=> #object...
(x 1)
I am a function=> nil
示例intern
:
(defn mkfn [func]
(intern *ns* func (fn [a] (print "I am a function"))))
=> #'user/mkfn
(mkfn 'y)
=> #'user/y
(y 1)
I am a function=> nil
至于你的錯誤,def
是一種特殊的形式,所以它有不同的評估規則。它不評估第一個引數,它必須是一個符號 - 和 (未評估) (eval 'y)
,'y
或者(symbol "y")
不是符號,而y
is。
uj5u.com熱心網友回復:
你需要一個宏,因為你需要撰寫代碼。
(defmacro mkfn [func]
`(fn ~func [~'a] ...))
uj5u.com熱心網友回復:
有兩種方法,函式加eval
或宏。如果您真的想以編程方式使用您選擇的名稱創建一個新函式,那么宏解決方案就是您要走的路。
function eval 解決方案具有指導意義,但您必須在呼叫函式時參考函式名稱(通過 2nd eval
),或者在創建函式時將創建的函式保存在另一個變數中。
如果您對撰寫宏感興趣,請先查看另一個問題: 如何撰寫 Clojure 執行緒宏?
對于函式 eval
,我們可以從我最喜歡的模板專案開始,添加以下內容:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn maker-eval
[fn-sym]
(let [ll (list 'fn 'anon-fn [] (str "I am " fn-sym))]
(spyx :eval ll)
(eval ll)))
(verify
(let [anon-fn-1 (maker-eval 'aaa)]
(is= "I am aaa" (anon-fn-1))) ; need the temp local variable
(let [anon-fn-2 (maker-eval 'bbb)]
(is= "I am bbb" (anon-fn-2))) ; need the temp local variable
)
我們可以看到函式的創建和使用,以及列印輸出:
:eval ll => (fn anon-fn [] "I am aaa")
:eval ll => (fn anon-fn [] "I am bbb")
對于宏版本,我們輸入
(defn maker-macro-impl
[fn-sym]
(let [ll `(defn ~fn-sym [] (str "I am " (str (quote ~fn-sym))))]
(spyx :macro ll)
ll))
(defmacro maker-macro
[fn-sym] (maker-macro-impl fn-sym))
(verify
(let [anon-fn-3 (maker-macro-impl 'ccc)]
(is= anon-fn-3 (quote
(clojure.core/defn ccc [] (clojure.core/str "I am " (clojure.core/str (quote ccc)))))))
(maker-macro ddd)
(is= (ddd) "I am ddd"))
并查看列印:
:macro ll => (clojure.core/defn ccc [] (clojure.core/str "I am " (clojure.core/str (quote ccc))))
請注意,區域變數anon-fn-3
僅用于測驗maker-macro-impl
函式,而不需要ddd
在單元測驗結束時呼叫新創建的函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/506828.html