2

クロージャーを使用する関数は、 で使用すると壊れるように見えevalます。

(eval {:fn (let [x "foo"] (fn [] "x"))})
;=> {:fn #<user$eval14716$fn__14717 user$eval14716$fn__14717@1ddd735>}

(eval {:fn (let [x "foo"] (fn [] x))})
;=> IllegalArgumentException No matching ctor found for class user$eval14740$fn__14741 
;   clojure.lang.Reflector.invokeConstructor (Reflector.java:166)

これがバグなのか、意図的に許可されていないものなのかを知るには、Clojure(またはクロージャ)について十分に知りません。誰かがこれに光を当てることができますか?

編集:明確にするために、eval関数オブジェクトを処理する方法について具体的に話しています。私の知る限りeval、実際には関数を含むJavaオブジェクトで動作するように設計されています。clojure の Web サイトにある例で(eval (list + 1 2 3))は、関数オブジェクトを に渡しますeval

4

3 に答える 3

3

Cloure'sevalは関数オブジェクトを完全にはサポートしていません。問題を引き起こすのは必ずしも閉鎖でさえありません。

たとえば、これは Clojure 1.0.0では機能しませんでした:

(eval {:fn (fn [x] x)})

しかし、これはしました:

(eval (fn [x] x))

最初の例は修正されました。以下も機能します。

(eval (let [x "foo"] (fn [] x)))

しかし、以下はまだ機能しません。

(eval {:fn (let [x "foo"] (fn [] x))})

コンパイラの 1 行に絞り込むことはできませんが、リテラル オブジェクト (clojure.lang.Compiler$ObjExpr だと思います) がevalさまざまなコンテキストでどのように処理されるかについてです。たとえば、式の「先頭」と別のデータ構造内。

eval一般に、Clojure でオブジェクトがクロージャであるかどうかに関係なく機能することに依存することはできないと思います。主に のようなものの説明を単純化するために、いくつかの単純な例でたまたま機能し(eval (list + 1 2))ます。マクロは、コンパイルされた関数ではなく、常にリテラル ソース コードをデータ構造として返す必要があります。

于 2012-07-02T02:19:02.637 に答える
1

これはバグではありません。(eval (list + 1 2 3))「閉鎖」と同等のものは(eval (list fn [] "foo"))ではなく (eval (fn [] "foo"))です。

そして(eval (list fn [] "foo")) => Can't take value of a macro: #'clojure.core/fn、そのようなことをするべきではないことを再度示しています (とにかくその必要はありません)。

于 2012-06-26T07:29:08.937 に答える
1

引数を eval に引用してみてください:

(eval '{:fn (let [x "foo"] (fn [] x))})
;=> {:fn #<user$eval345$fn__346 user$eval345$fn__346@17b6dd83>}
((:fn *1))
;=> "foo"
于 2012-06-25T15:37:44.250 に答える