2
((#(%a %b') {a:1 b:2}) {a:3 b:4}) -> (1 4)

JavaScript では、次のようになります。

(function(x){ return function(y){ return [x.a,y.b]; }})({a:1,b:2})({a:3,b:4});
Output: [1,4]

つまり、言い換えると、(Clojure の現在の実装とは異なり) ネストされた関数を許可するラムダの短い構文です。

4

3 に答える 3

4

マクロを使用せずにそのままの Clojure コード (つまり、JavaScript バージョンと同等) でそれを行いたい場合は、次のようにします。

(((fn [x] (fn [y] (list (:a x) (:b y)))) {:a 1 :b 2}) {:a 3 :b 4}) 
=> (1 4)

実際のマクロ識別子以外の別の形式を選択すれば、マクロでこれを行うことも#()できます。たとえば、次のようにすることができます。

(((my-lambda %a %b) {:a 1 :b 2}) {:a 3 :b 4}) 
=> (1 4)

(ps元の質問からマップキーワードを修正しましたが、機能しa:1ません.....)

アプローチは次のようになります。

  • というマクロを作成します。my-lambda
  • このマクロは、渡されたシンボルを調べて、自動生成されたシンボルに対するキーワード ルックアップに変換します。
  • 次のような自動生成シンボルを使用した関数の出力コード:(fn [sym1] (fn [sym2](list (:a sym1) (:b sym2))))

このアプローチは、ネストされた関数で完全にうまく機能します。Clojure ラムダについて知っておくべき重要なことは、 (fn [...] ...)入れ子にすることはできますが、#(...)できないということです (そうしないと、関数パラメーターがあいまいになるため)。

#()Clojure はリーダー マクロをまだサポートしていないため、構文を直接オーバーライドすることはできません。実際、これは良いことだと思います-構文の任意の再定義を許可すると、明らかな利点がないためにかなり保守しにくいコードを書く人がいる可能性があります(タイピングの数文字を節約できますが、読みやすさ/コード理解の低下に苦しむことは私の見解では利点ではありません)。

Clojure コードのどこを見ても#()、それは通常の無名関数であり、誰かが何か奇妙なことをするために再定義した可能性について心配する必要はないと思います。

于 2012-09-05T03:00:05.043 に答える
2

匿名リーダー マクロ#( )構文では、特定の引数がどの関数に対応するかが不明確になるため、ネストされた匿名関数は許可されません%2。人々はメーリング リストであいまいさを解決する方法を提案してきました。コンセンサスは、この(fn [arg] ...)フォームはほとんどの設定で使用するのに十分短く明確であるということです。場合によっては、ネストされた%2解決策が明確または簡潔ではない場合があります。

(function(x){ return function(y){ return [x.a,y.b]; }})

次のように書くことができます

(fn [x] (fn [y] [(.x a) (.y b)]))

Clojure はユーザー定義のリーダー マクロを意図的にサポートしていないため、ネストされた関数を許可する独自のリーダー マクロを追加することは困難です。

于 2012-09-04T20:50:06.613 に答える