こんにちは!はこです。
AutoLISPを独学し、5年以上業務で使用しています。
AutoLISPってなに?という方はまずこちらの記事をご覧ください。
AutoCADユーザーがAutoLISPを覚えるべきメリット3選
今回の記事では関数「car」「cdr」について解説していきます。
AutoLISPのリストはその中身をcar部、cdr部と呼ばれる2つのエリアに分けることができます。関数「car」「cdr」は car部、cdr部 を取得できるAutoLISP独特の関数です。
関数の使用例だけでなく、リストの構造についても触れていきますのでぜひご覧ください。
【AutoLISP】car部とcdr部を取得する関数「car」「cdr」
car部とcdr部ってなに?
リストはその中身をコンスセルと呼ばれる箱で表現できます。コンスセルは内部が2つのエリアに分かれており、左側のエリアをcar部、右側のエリアをcdr部と呼びます。
ちなみに、コンスセルで表現されるリストはコンスセル型リストまたはコンスといいます。
リストの構造
リストはcar部に要素が格納され、cdr部には次のコンスセルへのポインタが格納される構造になっています。
ポインタとは簡単にいうとメモリ上の番地を表し、次のコンスセルへのリンクとして機能するものです。
コンスセルが要素の数だけポインタを介してつながり、最後のcdr部にはポインタではなくnilが格納されることでリストの最終を表します。
例えば、("a" "b" "c")というリストを図で表現すると次のようなイメージです。
また、要素にリストを含む場合はcar部にもポインタが格納されます。(("a" "b") "c")のイメージは次のようになります。
要素がすべてドット対のリストを連想リストと呼びます。
ドット対についてはこちらの記事で解説していますのでご覧ください。
【AutoLISP】リストを作成する関数「list」「cons」
((0 . "a") (1 . "b") (2 . "c"))のイメージは次のとおりです。
それでは関数の動作と書式について解説していきます。
carの動作
car部を取得する
carは引数に指定したリストのcar部を取得する関数です。下記のリストを例に説明します。
(1 2 3)
carの記述は次のとおりです。引数となるリストはlistで作成しています。
(car (list 1 2 3))
(1 2 3)のcar部は1なので返り値は1となります。
また、リストは座標を表現することもできるため、carを実行するとX座標の取得が可能です。
carの書式
carの構文と引数および返り値は次のようになります。
- (car lst)
- lst
- car部(先頭の要素)を取得するリスト。
- 引数のcar部 / nil
- 引数に指定したリストのcar部が返る。空のリストの場合はnilを返す。
cdrの動作
cdr部を取得する
carに対してcdrはリストのcdr部を取得する関数です。
(1 2 3)
上記のリストはcarの説明でも取り上げた例ですが、このリストのcdr部を取得する場合は次のように記述します。
(cdr (list 1 2 3))
(1 2 3)のcdr部は(2 3)なので、返り値も(2 3)となります。
また、cdrで座標のY座標を取得しようとしてもリストの構造上、返り値はリストになってしまいます。
この場合、返り値に対してさらにcarを実行するといった工夫が必要です。
cdrの書式
cdrの構文と引数および返り値は次のようになります。
- (cdr lst)
- lst
- cad部(先頭の要素以外)を取得するリスト。
- 引数のcdr部 / nil
- 引数に指定したリストのcdr部が返る。空のリストの場合はnilを返す。
carとcdrの組み合わせ
次のリストで2番目の要素(数値の2)を取得する場合を考えます。
(setq lst (1 2 3 4 5))
この場合、cdrの返り値に対してcarを実行することで取得することができます。
(car (cdr lst)
また、4番目の要素(数値の4)を取得するときはcdrをさらに追加します。
(car (cdr (cdr (cdr lst))))
しかし、何度もcarとcdrを記述する方法は面倒ですし、プログラムが見づらくなってしまうことが欠点です。
AutoLISPにはcarとcdrの組み合わせをシンプルに表現した関数があります。
2番目の要素は「cadr」、4番目の要素は「cadddr」という関数で取得することが可能です。
(car (cdr lst)) → (cadr lst)
(car (cdr (cdr (cdr lst)))) → (cadddr lst)
ただし、carとcdrを組み合わせた関数は4段階の深さまでしかサポートされていません。5番目以降の要素を取得したい場合はn番目の要素が取得できる関数「nth」を使用してください。
まとめ
今回のまとめ
- リストはコンスセルという箱が連鎖的につながって構成されている
- コンスセルの内部はcar部とcdr部の2つのエリアに区分けできる
- car部にはリストの要素、cdr部には次のコンスセルへのポインタが格納されている
- carとcdrを組み合わせは1つの関数でシンプルに表現できる(4段階の深さまで)