2017-09-28 10 views
0

私は学校でLispを勉強しています。作成しなければならないプログラムの1つは、mapcanを使ってremove-if-notの機能を複製するものです。私はプログラムを作成し、正しく動作しますが、私は出力を理解していません。なぜこのプログラムは原子のリストを返しますか?

私が実行した場合具体的には、:

(findall 'numberp '(1 a 3)) 

出力は次のとおりです。(1 3)

プログラムは以下の通りです:

(defun findAll (fct l) 
(cond 
     ((null l) nil) 
     ((mapcan (lambda(x) (if (funcall fct x) (list x) nil)) l)) 
    ) 
) 

ソリューションの私の理解があります次のようになります: "リストの要素のそれぞれについてlambda関数を呼び出します。関数の結果がフィットし、要素xがtrueを返した場合、要素su最終的に "list(x)"を連続して呼び出すと、(1 2)のようなアトムのリストが返されます。

答えて

6

あなたの質問にSLIDEというタグが付いている理由がわかりません。これはIDEです。

コードを読み込み可能な状態にしてインデントしましょう。

(defun findAll (fct l) 
    (cond 
    ((null l) nil) 
    ((mapcan (lambda (x) 
       (if (funcall fct x) 
        (list x) 
       nil)) 
      l)))) 

それはそのように書くことは可能ですが、通常我々は最後の句は常に呼ばれていることを明確にするT条件を持っています。

(defun findAll (fct l) 
    (cond 
    ((null l) nil) 
    (t (mapcan (lambda (x) 
       (if (funcall fct x) 
        (list x) 
        nil)) 
       l)))) 

MAPCANが既に空のリストを扱っているので、あなただけのCONDと最初の句を削除することができます。 findAllは、通常、find-allと呼ばれます。リストLコールラムダ関数の各要素について

(defun find-all (fn list) 
    (mapcan (lambda (item) 
      (if (funcall fn item) 
       (list item) 
       nil)) 
      list)) 

。要素xが真を返す関数フィットの結果とあれば、括弧で囲まれた要素を返し、そうでない場合はリストLISTコールラムダ関数の要素のそれぞれについて

nilを返します。関数FNと要素ITEMの結果がtrueを返した場合は、ITEMのリストを返し、そうでない場合は空のリストを返します。最終結果は、ラムダ関数のすべての結果リストの(破壊的に)追加されたリストです。

+0

しかし、なぜ最終結果が一緒に追加されますか?単なるリストの束ではありませんか? – edoreld

+1

@edoreld:MAPCANはこれを行います。そのドキュメントを参照してください:http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcan –

関連する問題