8

この関数ビルダーは、P.Graham の「ANSI Common Lisp」(110 ページ) で構成を実現するために使用されます。引数は、引用符で囲まれた n>0 関数名です。私はそれを完全には理解していないので、ここにコードを引用し、その下に私の質問を指定します:

(defun compose (&rest fns)
  (destructuring-bind (fn1 . rest) (reverse fns)
    #'(lambda (&rest args)
        (reduce #'(lambda (v f) (funcall f v)) 
                rest
                :initial-value (apply fn1 args)))))

構成する引数リストは反転されてアンパックされ、その (最初の) 要素が 'fn1' にバインドされ、残りが 'rest' にバインドされます。最も外側のラムダの本体は reduce: (funcall fi (funcall fi-1 ... ) ) であり、最初のオペランドを復元するためにオペランドの順序が逆になっています。

1) 最も外側のラムダ式の役割は何ですか? つまり、どこから「引数」を取得しますか? destructuring-bind の第一引数に指定したデータ構造ですか?2) 最も内側のラムダはどこから 2 つの引数を取りますか?

コードが何をするかは理解できますが、それでもレキシカルスコープは私にとって少し謎です。どんなコメントでもお待ちしております!前もって感謝します、//マルコ

4

2 に答える 2

11

最初にいくつかの実用的な例を検討すると、おそらく簡単です。

(defun compose1 (a)
  (lambda (&rest args)
    (apply a args)))

(defun compose2 (a b)
  (lambda (&rest args)
    (funcall a (apply b args))))

(defun compose3 (a b c)
  (lambda (&rest args)
    (funcall a (funcall b (apply c args)))))

したがって、最も外側lambdaは戻り値です。引数を受け取る関数であり、最後の関数を適用し、最後の関数から取得した結果に対して他のすべてを逆の順序でチェーンします。

注:compose1としてより簡単に定義できます(defun compose1 (a) a)

やや同等だが効率の悪いバージョンは

(defun compose (&rest functions)
  (if (= (length functions) 1)
      (car functions)
      (lambda (&rest args)
        (funcall (first functions)
                 (apply (apply #'compose (rest functions))
                        args)))))
于 2013-10-17T12:00:06.427 に答える
2

1) (combine ...) の結果は他の関数の構成を計算する関数であるため、最も外側のラムダはクロージャを作成します。

2) 最も内側のラムダは関数 reduce から ists 引数を取得します。Reduce は 2 つの引数の関数 (最も内側のラムダ) を取り、それを段階的にリストに適用します。

 (reduce #'- '(1 2 3 4))  is   (- (- (- 1 2) 3) 4)
于 2013-10-17T11:48:39.957 に答える