ほとんどの Lisp 言語のように、clojure にはコンス セルがないと聞きました。
それは、clojure リストが空のリストで終わらないということですか?
誰かがそれが正確に何を意味するのか説明できますか?
ほとんどの Lisp 言語のように、clojure にはコンス セルがないと聞きました。
それは、clojure リストが空のリストで終わらないということですか?
誰かがそれが正確に何を意味するのか説明できますか?
Lisp は基本的な cons データ構造とその表記法を提供します。
その章では次のことを紹介しています。
( a . b )(a b c)nilリストを終了する原子記号car、cdr、cons、eqおよびatomff, subst, equal, null, cadr, caddr, null, append, among, pair, assoc, ...sublisapplyevalLispの早い段階で、コンス セルを変更する関数が追加さrplacaれました。John McCarthy らによる LISP 1.5 Programmer's Manualを参照してください。1962年から。これらの関数を使用すると、破壊的な関数を記述したり、巡回リストのような巡回コンスベースのデータ構造を作成したりできます。rplacd
Common Lisp
通常、Lisp 方言はこれのほとんどを実装しています。Common Lisp も例外ではなく、この機能は Common Lisp 標準のConsesに記述されています。上記の関数を使用した例:
; pair two lists into a list of cons cells.
; the function pair is called pairlis in Common Lisp.
CL-USER 17 > (pairlis '(john mary eva) '(34 29 40))
((EVA . 40) (MARY . 29) (JOHN . 34))
; find a cons cell in a list of cons cells,
; based on the content of the car of those cons cells
CL-USER 18 > (assoc 'eva (pairlis '(john mary eva)
'(34 29 40)))
(EVA . 40)
; create a tree out of cons cells and atoms
CL-USER 19 > (cons (cons 10 20) (cons 30 40))
((10 . 20) 30 . 40)
; a cons cell is not an atom
CL-USER 20 > (atom (cons 1 2))
NIL
; a cons cell is not nil
CL-USER 21 > (null (cons 1 2))
NIL
; substitute an item with a new one in a tree
CL-USER 22 > (subst 30 ; new
'bar ; old
'((10 . 20) . (bar . 40))) ; tree
((10 . 20) 30 . 40) ; also written as ((10 . 20) . (30 . 40))
; substitute several items in a tree, using an assoc list
; to describe the substitutions
CL-USER 23 > (sublis '((a . 10) (d . 40)) ; substitutions
'((a . b) . (c . d))) ; tree
((10 . B) C . 40)
リストは記号式の特殊なケースです。それらは通常、ドットなしで書かれます。
CL-USER 24 > '(a . (b . nil))
(A B)
Common Lisp は変更操作rplacaとrplacdLisp 1.5 もサポートしています:
CL-USER 25 > (let ((c (cons 0 1))) ; create a cons
(print c) ; print it
(print (rplaca c 'foo)) ; replace the car
(print (rplacd c 'bar)) ; replace the cdr
(print (eq c (rplaca c 'baz))) ; identical ?
(values))
(0 . 1) ; the cons cell
(FOO . 1) ; car replaced
(FOO . BAR) ; cdr replaced
T ; still the same object
Emacs Lisp
Emacs Lisp も上記の機能を実装しています。
ELISP> (sublis '((a . 10) (d . 40))
'((a . b) . (c . d)))
((10 . b) c . 40)
クロージャ
Clojureは、John McCarthy が説明したこれらのシンボリック式をサポートしていません。コンスセルやドット表記がなく、上記のインターフェースを提供しません。たとえば、Atom はClojure ではまったく異なるものを意味します。consコンスセルを作成しません。リストはコンスセルで構成されていません。
Clojure では、ドットは単なる別の記号です。
user=> (count '(1 . 2))
3
リストを構築するためのプリミティブ関数があります:
user=> (list 1 2 3)
(1 2 3)
結果はリストになるはずです:
user=> (list? (list 1 2 3))
true
と呼ばれる関数がありますcons:
user=> (cons 0 (list 1 2 3))
(0 1 2 3)
どういうわけか、これはリストではありません:
user=> (list? (cons 0 (list 1 2 3)))
false
基本的に、Clojure は独自の命名法とセマンティクスを持つさまざまなデータ構造 (->シーケンス、論理リスト) を使用します。名前が Lisp の名前に似ていても、同じことを期待しないでください。
図式
プログラミング言語Schemeも、上記と同様のコンスセルを提供します。いくつかの機能が欠けていますが、簡単に実装できます。たとえばsublis、Scheme では次のように実装できます ( initdr.scmを参照)。
(define (sublis alist tree)
(if (pair? tree)
(cons (sublis alist (car tree))
(sublis alist (cdr tree)))
(if (assv tree alist)
(cdr (assv tree alist))
tree)))
clojure.lang.Cons.cons呼び出しの結果に使用されますrest/cdr
はシーケンスであり、 . ではありませんObject。consリスト、ベクトル、または遅延シーケンスに何かを追加すると、Cons.Consしかし、他の回答から明らかなように、 esを扱う関数はありません。それらはすべて、一般的にシーケンスを扱います。もう 1 つの用途:conj不確定なシーケンス (ベクトル リストでもセットでもマップでもない ...) に ing を使用すると、Cons.
Common Lisp では、リストは一連のコンス セルです。各コンスセルには、「car」と「cdr」と呼ばれる 2 つのスロットまたはポインターがあります。車は何かを指しています (または保持しています)。cdr は通常、別のコンス セルまたはnil. nilリストの最後としてカウントされます。Clojure はそのリストでほぼ同じ機能を提供しますが、基本的な表現は異なります。というデータ型Consがありますが、すべてのリストまたは特定のリストのすべての部分が から構築されているわけではありませんCons。(まだ読んでいない場合は、jmargolisvt の回答を読む必要があります。) [編集: 他の回答は、Clojure のリストとコンスの関係についてここで述べていることが正しくないことを示しています。「リスト」の非公式な意味で正しいと感じるかもしれませんが、そうではないかもしれません.]
また、部分的にシーケンスの抽象化の考え方が原因で、Clojure ではリスト自体が Common Lisp や Scheme よりもはるかに一般的ではないことに注意してください。ただし、他の種類のシーケンスは非常に一般的です。
また、Clojure では、印刷したときにリストのように見えるものを実際にはリストであると想定できないことも知っておく価値があります。たとえば、リストとは見なされない遅延シーケンスである可能性があります。
リストを使用した有益な Clojure の例を次に示します。
user=> (def foo (list 1))
#'user/foo
user=> foo
(1)
user=> (class foo)
clojure.lang.PersistentList
user=> (def bar (cons 2 foo))
#'user/bar
user=> bar
(2 1)
user=> (class bar)
clojure.lang.Cons
(異なるデータ型を返しますが、両方ともリストと見なされますfoo。 )barclass
user=> (next bar)
(1)
user=> (rest bar)
(1)
user=> (class (next bar))
clojure.lang.PersistentList
user=> (class (rest bar))
clojure.lang.PersistentList
user=> (next foo)
nil
user=> (rest foo)
()
user=> (= nil ())
false
user=> (rest ())
()
user=> (rest nil)
()
user=> (next ())
nil
user=> (next nil)
nil
Common Lisp では、オブジェクトをリストや 以外の別のオブジェクトにコンスできますnil。結果は aa "dotted list"です。これは、通常のリストのように(1 . 2)、 cdr ポインタが別のコンス セルまたは 以外のものを指す単一のコンス セルです。nilClojure で試してみましょう。
user=> (cons 1 2)
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:528)
私がそうしている間に、Common Lisp とのもう 1 つの顕著な違い ( nil= ()= false):
user=> (= nil false)
false
user=> (= () false)
false
ただし、 でnilはありませんがfalse、次のように使用できますfalse。
user=> (if nil "nil works like true" "nil works like false")
"nil works like false"
ただし、空のリストではそれを行うことはできません。
user=> (if () "() works like true" "() works like false")
"() works like true"
(これらの例にもかかわらず、概して、Clojure は Common Lisp よりもはるかに単純でエレガントです。IMO です。Common Lisp を愛している人でさえ、(私のように)、Common Lisp は単純でもエレガントでもないことを認めなければなりません。ある種の美しさ。)