実行時にfnを完全に生成したい(つまり、名前とargシンボルはコードではなく実行時に決定されます) これを達成する最も良い方法は何ですか?Clojure:実行時に関数を作成する方法
たとえば、次の機能を実装するにはどうすればよいですか?名前、引数と体が符号化されていない機能が、ランタイム
実行時にfnを完全に生成したい(つまり、名前とargシンボルはコードではなく実行時に決定されます) これを達成する最も良い方法は何ですか?Clojure:実行時に関数を作成する方法
たとえば、次の機能を実装するにはどうすればよいですか?名前、引数と体が符号化されていない機能が、ランタイム
(defn gen-fn
[n as b]
(let [n (symbol n)
as (vec (map symbol as))
fn-value (eval `(fn ~n ~as ~b))]
(intern *ns* n fn-value)))
そして、いくつかの使用で決定することができ
(gen-fn "my-func-name" (symbol "x") (symbol "y") (println "this is body. x=" x))
注:このように使用されるだろう
(defn gen-fn [name arg-symbols body]
...
...
:
user=> (gen-fn "foo" ["x"] '(do (println x) (println (inc x))))
#'user/foo
user=> (foo 5)
5
6
nil
ただし、私はこのアプローチが本当に好きではありません。それは本当に難しいにおいがあります:eval
。なぜ実行時にグローバルを生成したいのですか?私は間違った名前空間や他の厄介な問題をさまざまな問題に抱えています...
私は確信していませんが、あなたはevalよりも優れたマクロでこれを行うことができると信じています。
(defmacro gen-fn
[n as b]
(let [n (symbol n)
as (vec (map symbol as))]
`(intern *ns* n (fn ~n ~as [email protected]))))
これは実行時には機能しません。ポイントは、事前に 'n'、' as'と 'b'を知る必要があることです。そして、あなたはできる:(defmacro gen-fn [n as b] '(defn ~(symbol n) ~(vec (map symbol as)) [email protected]))
。 'eval'アプローチでは、' gen-fn'への引数は任意の計算の結果になる可能性があります。 –
kotarak
もう一つの方法は、 "文字列を読み" "evalの" を使用している:
ユーザー=>(DEF F1(evalの(読み取り、文字列を "(FN [XY](* XY))") ))
# 'ユーザ/ F1
ユーザー=>(F1 3~5)
はい。これは醜いものです。私がこれを必要とするのは、ClojureのGeneticProgrammingを実験しているからです。 Clojureはこれに本当に自然なようです。 – GabiMe
ああ。 OK。 GPは 'eval'を法的に使うことができます。しかし、 'eval'を使って奇妙な結果に気をつけてください。 – kotarak
なぜeval?マクロでこれを行うことはできませんでしたか? –