2

関数のリスト、要素のリストがあり、すべての要素にすべての関数を適用し、結果のすべてのリストを一緒に追加したいと思います。私は次のようにしました

(defun apply-functions(funcs elements)
    (if (null funcs)
        nil
        (append (mapcar #'(lambda (x) (funcall (car funcs) x)) elements) (apply-functions (rest funcs) elements))))

意図したとおりに動作しますが、私はそれが好きではありません。よりクリーンで簡潔な方法はありますか? 私は Lisp に慣れていませんが、Lispish スタイルの作業にはまだ慣れています。

4

3 に答える 3

6

これはあなたのものと同じアイデアですが、より短いものです:

(defun apply-functions (functions elements)
  (mapcan #'(lambda (x) (mapcar x elements)) functions))
于 2012-10-17T18:53:04.500 に答える
6

あなたがマクロが好きかどうかはわかりませんがloop(私は誰かを台無しにしたくありません)、これを試してください:

(defun apply-functions (fs es)
    (loop for f in fs appending (mapcar f es)))
于 2012-10-17T15:52:12.133 に答える
4

call-each新しい関数を返す関数を定義し、その引数で各関数を呼び出すリストを返します。

(defun call-each (fns)
  (lambda (arg)
    (mapcar (lambda (fn)
              (funcall fn arg))
            fns)))

(funcall (call-each (list #'third #'second #'first)) '(a b c))
;=> (C B A)

cl には、mapcan基本的に nconc+である機能がありmapcarます。

(mapcan #'reverse '((a b c)
                    (e f g)
                    (h i j)))
;=> (C B A G F E J I H)

(mapcan (call-each (list #'identity #'1+)) '(1 3 5 7 9))
;=> (1 2 3 4 5 6 7 8 9 10)  

残念ながら、nconcmapcan使用する は破壊的です。

(let ((data '((a b c)
              (d e f)
              (g h i))))
  ;;here be dragons
  (list (mapcan #'identity data)
        data))
;=> ((A B C D E F G H I) ((A B C D E F G H I) (D E F G H I) (G H I)))

alexandria救助へ:

(let ((data '((a b c)
              (d e f)
              (g h i))))
  ;;safe version
  (list (alexandria:mappend #'identity data)
        data))
;=> ((A B C D E F G H I) ((A B C) (D E F) (G H I)))

を使用する方が効率的であることに注意してmapcanください。ただし、データの取得元と所有者が正確にわかっていない限り、使用mappendする方法をお勧めします。

だからあなたは書くことができます:

(defun apply-functions (fs es)
  (when fs
    (alexandria:mappend (call-each fs) es))

(apply-functions (list #'identity #'1+) '(1 3 5 7 9))
;=> (1 2 3 4 5 6 7 8 9 10)
于 2012-10-17T19:05:15.453 に答える