web-dev-qa-db-ja.com

Schemeの `cons`がどのように機能するかを説明するのに役立ちますか?

これは、リストの最後の要素を削除する関数です。

_(define (remove-last ll)
  (if (null? (cdr ll))
      '()
      (cons (car ll) (remove-last (cdr ll)))))
_

したがって、私の理解では、リストをcons(たとえば、空のリストを持つ_a b c_、つまり'()の場合、_a b c_を取得する必要があります。ただし、相互作用でテストするwindows(DrScheme)、結果は次のとおりです。

If(cons '()'(a b c))

_(() a b c)
_

If(cons '(a b c)'())

_((a b c))
_

私は一体何のようです:(!それから私は私の問題に戻り、隣接する重複を持つすべての要素を削除します。たとえば、_(a b a a c c)_は_(a b)_になります。

_(define (remove-dup lst)
  (cond ((null? lst) '())
        ((null? (cdr lst)) (car lst))
        ((equal? (car lst) (car (cdr lst))) (remove-dup (cdr (cdr lst))))
        (else (cons (car lst) (car (cdr lst))))
        )

  )
_

正しくありませんでしたが、答えは_._の間に_a b_があることに気付きました。これはどのように起こりますか?

_`(a . b)`
_

上記のコードではconsへの呼び出しは1つだけで、どの部分がこの_._を生成できるかわかりませんでした。何か案が?

ありがとう、

11
Chan

consビルドペア、リストではありません。 LISPインタープリターは、「ドット」を使用して、ペアの要素を視覚的に分離します。したがって、_(cons 1 2)_は_(1 . 2)_を出力します。 carcdrはそれぞれ、ペアの最初と2番目の要素を返します。リストはペアの上に作成されます。ペアのcdrが別のペアを指している場合、そのシーケンスはリストとして扱われます。最後のペアのcdrは、null'()で表される)と呼ばれる特別なオブジェクトを指し、これはインタープリターにリストの最後に到達したことを通知します。たとえば、リスト'(a b c)は、次の式を評価することによって作成されます。

_> (cons 'a (cons 'b (cons 'c '())))
(a b c)
_

listプロシージャは、リストを作成するためのショートカットを提供します。

_> (list 'a 'b c)
(a b c)
_

式_(cons '(a b c) ())_は、最初の要素がリストであるペアを作成します。

_remove-dup_プロシージャは、else句でペアを作成しています。代わりに、_remove-dup_を再帰的に呼び出し、その結果をペアの2番目の要素として配置することにより、リストを作成する必要があります。手順を少し整理しました。

_(define (remove-dup lst)
  (if (>= (length lst) 2)
      (if (eq? (car lst) (cadr lst))
          (cons (car lst) (remove-dup (cddr lst)))
          (cons (car lst) (remove-dup (cdr lst))))
      lst))
_

テスト:

_> (remove-dup '(a b c))
(a b c)
> (remove-dup '(a a b c))
(a b c)
> (remove-dup '(a a b b c c))
(a b c)
_

[〜#〜] sicp [〜#〜] のセクション2.2(階層データとクロージャープロパティ)も参照してください。

完全を期すために、これは_remove-dup_のバージョンであり、すべての同一の隣接する要素を削除します。

_(define (remove-dup lst)
  (if (>= (length lst) 2)
      (let loop ((f (car lst)) (r (cdr lst)))
        (cond ((and (not (null? r))(eq? f (car r)))
               (loop f (cdr r)))               
              (else
               (cons (car lst) (remove-dup r)))))
      lst))
_
28
Vijay Mathew

ここで擬似コード:

クラスペア{オブジェクト左、オブジェクト右}。

function cons(Object left、Object right){return new Pair(left、right)};

したがって、1。cons( 'A、' B)=> Pair( 'A、' B)2。cons( 'A、NIL)=> Pair(' A、NIL)3。cons(NIL、 'A)= > Pair(NIL、 'A)4。cons(' A、cons( 'B、NIL))=> Pair(' A、Pair( 'B、NIL))5。cons(cons(' A'B)、 NIL))=>ペア(ペア( 'A、' B)、NIL)

すべての場合の左と右を見てみましょう:1。'Aと 'Bはアトムであり、ペア全体はリストではないため、(const'a' b)はスキーム2で(a .b)を返します。NILは空のリストです'Aはアトム、(cons' a '())はリスト(a)3。NILと' Aは上記のとおりですが、左はlist(!)、(cons '()' a)はペア(( )。a)4。簡単なケースです。ここに適切なリストがあります(ab)。 5.適切なリスト、頭はペア(a。b)、尾は空です。

うまくいけば、あなたはアイデアを得ました。

あなたの機能について。あなたはLISTに取り組んでいますが、PAIRSを構築しています。リストは(ペアの)ペアですが、すべてのペアがリストであるとは限りません!リストペアになるには、テールとしてNILが必要です。

(a b)ペアとリスト(a。b)リストではないペア

短所にもかかわらず、関数にエラーがあり、 '(a b a a c c d)では機能しません。これはあなたの質問とは関係がないので、ここでは修正を投稿しません。

1
paul