11

私は LISP での関数型プログラミングについて少し学んでいますが、ここで遭遇したことがあります。LISP は CAR、CDR 関数、および FIRST 関数と REST 関数を使用しています。どちらもリストに関連しています。

これまでに学んだことから、これら2つには違いがありますが、違いが何であるかはよくわかりません.

誰か私のためにこれを要約できますか?また、最終的に CDR、CAR を使用して FIRST/REST を実装するにはどうすればよいですか?


編集:受け入れられた回答はドキュメントに言及していますが、リンクしていないため、ここにCAR/CDRのドキュメントへのリンクがあり、次にFIRST/RESTのリンクがあります。

さらに、重要な注意事項として、リンクされたドキュメントは、一般的に使用される環境である CLISP の「単なる実装ノート」です。一般に、このような言語の「公式ドキュメント」を見つけることはほとんど不可能です。

4

4 に答える 4

14

それらが何をするかという点では、carcdrはfirstrestと同等です。これは、ドキュメントで非常に明確です。HyperSpec は、firstsecond、 &cのエントリについて次のように述べています。

最初、2 番目、3 番目、4 番目、5 番目、6 番目、7 番目、8 番目、9 番目、10 番目の関数は、それぞれ list の 1 番目、2 番目、3 番目、4 番目、5 番目、6 番目、7 番目、8 番目、9 番目、10 番目の要素にアクセスします。具体的には、

(first list)    ==   (car list)
(second list)   ==   (car (cdr list))
(third list)    ==   (car (cddr list))

ノート:

1 番目は機能的に car と同等、2 番目は機能的に cadr と同等、3 番目は機能的に caddr と同等、4 番目は機能的に cadddr と同等です。

これらの関数を使用する場合、機能ではなくスタイルに違いがあります。これは実際にはHyperSpecでも呼び出されます。たとえば、restのエントリで:

ノート:

議論がコンスとしてではなくリストとして主観的に見られることである場合、restはしばしばcdrよりもスタイル的に好まれます。

たとえば、コンス セルから構築された構造体をマッピングする 2 つの方法を考えてみましょう。最初に、コンス セルのツリーにマッピングし、ツリーの各リーフ (つまり、非コンス) で何らかの関数を呼び出します。conspで何かが cons であるかどうかをチェックし、cons である場合はそのcarcdrに再帰します。consを呼び出して、結果を新しいコンス セルに結合します。

(defun map-over-cons (function tree)
  (if (not (consp tree))
      (funcall function tree)
      (cons (map-over-cons function (car tree))
            (map-over-cons function (cdr tree)))))

別の方法として、リストをマッピングする場合、通常はendp (またはnullですが、endpは単にnilを探すのではなく、リストの終わりを探していることを強調しています) を使用して終了条件をチェックし、関数を呼び出します。リストの最初に戻り、リストの残りの部分に再帰します。consを使用して構築された結果を見るのはかなり一般的ですが、実際にはlist*があり、リストが構築されていることを強調する 2 つの引数で呼び出されたときに同じタスクを実行します (一般に、もう少し多くのことができます) 。

(defun map-over-list (function list)
  (if (endp list)
      '()
      (list* (funcall function (first list))
             (map-over-list function (rest list)))))

これらの関数のいずれも、 car 、 cdr 、および cons を使用するか、 first 、 rest 、および list* 、またはそれらの任意の組み合わせを使用して記述できますがいずれ一方固執する後でコード読む可能性のある人々に役立ちます(オリジナルを含む)著者)、および著者の意図を示します。

また、最終的に CDR、CAR を使用して FIRST/REST を実装するにはどうすればよいですか?

どうですか:

(defun first (x) (car x))
(defun rest (x) (cdr x))

または、 symbol-functionがある場合はさらに良いでしょう:

(setf (symbol-function 'first) (symbol-function 'car))
(setf (symbol-function 'rest) (symbol-function 'cdr))
于 2015-04-28T13:39:29.227 に答える
4

リストで作業している操作firstrestシグナル: 空のリストで終わる一連のペア、つまり (リスト x1 ... xn) の形式です。

ペアで構築されたデータ構造で作業している操作carcdr信号は、リストではない可能性があります。

それは、他の人がコードを読みやすくするために、リストを操作するときにfirst選択することです。rest

于 2015-04-28T11:38:36.457 に答える
3

古典的には、car と cdr はより機械指向であり、first と rest はより抽象的な関数でした。実際には、それらの間に違いはありません。誰もが car と cdr に固執したため、car と cdr が優勢でした。

car と first の違いを見つけるのに苦労している場合、それは違いがないからです。最初は car のエイリアスとして見てください。

定義?

(defun first (x) (car x))
(defun rest (x) (cdr x))
于 2015-04-27T23:06:12.060 に答える
2

まず、これらはいずれも述語ではありません (少なくとも、Lisp プログラマーが「述語」と呼ぶものではありません。このコンテキストでは、「述語」は「ブール値を返す関数」を意味します)。

質問に関しては、REPL に飛び乗ってみましょう。

; SLIME 2014-12-23
CL-USER> (describe #'car)
#<FUNCTION CAR>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Return the 1st object in a list.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value
CL-USER> (describe #'first)
#<FUNCTION FIRST>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Return the 1st object in a list or NIL if the list is empty.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value
CL-USER> (describe #'cdr)
#<FUNCTION CDR>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Return all but the first object in a list.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value
CL-USER> (describe #'rest)
#<FUNCTION REST>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Means the same as the cdr of a list.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value

したがって、ドキュメントとその署名によると、carは と同等でfirstあり、cdrと同等restです。これをテストしましょう。

CL-USER> (cons 1 2)
(1 . 2)
CL-USER> (car (cons 1 2))
1
CL-USER> (first (cons 1 2))
1
CL-USER> (cdr (cons 1 2))
2
CL-USER> (rest (cons 1 2))
2
CL-USER> (cons 1 nil)
(1)
CL-USER> (car (cons 1 nil))
1
CL-USER> (first (cons 1 nil))
1
CL-USER> (cdr (cons 1 nil))
NIL
CL-USER> (rest (cons 1 nil))
NIL
CL-USER> nil
NIL
CL-USER> (car nil)
NIL
CL-USER> (first nil)
NIL
CL-USER> (cdr nil)
NIL
CL-USER> (rest nil)
NIL

だから、彼らは同じようです。

于 2015-04-28T00:44:41.200 に答える