2011-12-19 11 views
4

を通して送信されたときにのClojureののfuncsは、ClojureのREPLでリスト

予想通り

(#(for [x %] (+ 100 (second x))) ['(+ 38) '(+ 48)]) 

が生成し、この式(138 148)、期待どおりに動作するように見えるが、これ

(#(for [x %] ((first x) 100 (second x))) ['(+ 38) '(+ 48)]) 
はありません

は本当に奇妙な(38 48)を生成します。

どちらの表現でも同じ結果が得られるはずです。 私は何が欠けていますか? この謎を解決するためのアイデアを感謝します。

ところで、私は 'apply(first x)'を使い、残りのargsをリストにパッケージングしようとしましたが、それは問題ではないようです。同じ予期しない結果が戻ってきます。また

は、+が実際入力から分解されることを確認するために、私はこの+

(#'clojure.core/+ #'clojure.core/+) as expected. 

答えて

10
(#(for [x %] ((first x) 100 (second x))) ['(+ 38) '(+ 48)]) 

を生成REPL

(#(for [x %] (resolve (first x))) '((+ 38) (+ 48))) 

に以下を与えましたシンボルは関数ではなく、リスト内で引用されているためです。しかし、シンボルは、関数として呼び出されたとき(キーワードと同じ)、マップルックアップを実行するものとして定義されます。だから('+ 100 38)(get 100 '+ 38)と同じです。その最後の議論は、 "あなたが私が地図で欲しいものを見つけることができなければ、それを返す"ことです。 100はマップではないので、+はその引数を戻り値として使用します。代わりに引用されたリストの

  1. 利用ベクトルが+が適切に解決されることを保証します。

    は、それはあなたが2つのオプションがあり、あなたがやりたいようにするには。

    (#(for [x %] ((first x) 100 (second x))) [[+ 38] [+ 48]]) 
    
  2. あなたの代わりに+シンボルの+機能を使用することを保証するために、それを自分で解決します。

    (#(for [x %] ((resolve (first x)) 100 (second x))) ['(+ 38) '(+ 48)]) 
    
+3

+1。問題が本当に引用されているので、データ構造を変更する必要はありません。リストも同様に機能します。リテラルフォームを削除して、たとえば'(list + 38)' – skuro

+0

すべての偉大な答えをありがとう。私が入力として使用していたリストのリストは、partitionを使って生成されたので、この形式の入力そのものを使いたいと思っていました。 私は、この問題を投稿した時点でベクトルに変換しましたが、評価されたfunc(REPLは#^を使って示しています)を生成したことに気づいたが、resolve(first x)の作業は、 (最初のx)呼び出しはエラーを生成するが、そうではなかった。 (get 100 '+ 38)は私のためにこれを解明しました。 – Don

3

リストを引用すると、'(+ 38)のように、リスト内の項目のいずれも評価されません。したがって、+は単なる記号であり、clojure.coreの加算関数への参照ではありません。

このシンボルを関数として呼び出すと、ちょっと混乱することがあります。特に、2つの引数を使ってこのシンボルを呼び出すことがあるためです。その理由は、すでに@mangeで説明した関数は第一引数にシンボルを検索しようとして、シンボルを呼び出すと、デフォルトとして(オプション)二番目の引数を返す検索が失敗したとき:

('x)  ; throws ArityException 
('x 1)  ;=> nil 
('x 1 2) ;=> 2 
('x 1 2 3) ; throws ArityException 

あなたは持っています

  1. 引用リストの代わりにベクトルを使用してください:[+ 38]。ベクトルのすべての要素は評価されます(引用符を付けられていないリストのように)が、ベクトルは単なるデータ構造であり、関数呼び出しの構文ではありません。
  2. シンボルによって参照される関数を見つけるには、resolve関数を使用します。 resolveは、現在の名前空間のシンボルを検索することに注意してください。したがって、引用されたリストの作成と関数の呼び出しが別々の名前空間で行われる場合、これは驚くべき結果につながります(別の名前空間で同じシンボルに対して2つの異なる定義があるとします)。
  3. 使用構文の代わりに、リスト上の引用シンプルの引用や記号をUNQUOTE(それを評価する):詳細な説明のための`(~+ 38)
+0

特に構文の引用例については、大きな洞察をいただきありがとうございます。入力として使用していたリストのリストは、partitionを使用して生成されました。 私は、この問題を投稿した時点でベクトルに変換しましたが、評価されたfunc(REPLは#^を使って示しています)を生成したことに気づいたが、resolve(first x)の作業は、 (最初のx)呼び出しはエラーを生成するが、そうではなかった。 マングとあなたの答えは私のためにそれを整理するのに役立ちました。 – Don