リスト

Last-modified: 2017-12-03 (日) 21:21:04

多くのLISP系言語と同じく、SKILL言語でもリストを扱うことができる。ただし、SKILL言語で扱うことができるのは、cdr部分が nil または consセル になっているもの*1だけである。

リテラル表現

特殊フォーム quote (または、その糖衣構文の「'」)を使ってリストのリテラルを表現できる。

(quote ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
'("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
'(("France" "Paris") ("Japan" "Tokyo"))
→ (("France" "Paris") ("Japan" "Tokyo"))

cons

(cons "Sapporo" (cons "Tokyo" (cons "Nagoya" (cons "Osaka" (cons "Fukuoka" nil)))))
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
(cons (cons "France" (cons "Paris" nil)) (cons (cons "Japan" (cons "Tokyo" nil)) nil))
→ (("France" "Paris") ("Japan" "Tokyo"))

list

(list "Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
(list (list "France" "Paris") (list "Japan" "Tokyo"))
→ (("France" "Paris") ("Japan" "Tokyo"))

car、cdr、last

(setq cities '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
(car cities)
→ "Sapporo"
(cdr cities)
→ ("Tokyo" "Nagoya" "Osaka" "Fukuoka")
(cadr cities) ; == (car (cdr cities))
→ "Tokyo"
(cddr cities) ; == (cdr (cdr cities))
→ ("Nagoya" "Osaka" "Fukuoka")
(caddr cities) ; == (car (cdr (cdr cities)))
→ "Nagoya"
(last cities)
→ "Fukuoka"

carはcitiesの最初の要素を返し、
cdrはcitiesの残りのリストを返す
lastはリストの最後の要素を返す

c****r(*の部分は「a」と「d」どちらか)にして重ねがけが可能 ※後方から順に処理していく事に注意!

関数説明
(caar x)(car (car x)) と等価
(cadr x)(car (cdr x)) と等価
(cdar x)(cdr (car x)) と等価
(cddr x)(cdr (cdr x)) と等価
(caaar x)(car (car (car x))) と等価
(caadr x)(car (car (cdr x))) と等価
(cadar x)(car (cdr (car x))) と等価
(caddr x)(car (cdr (cdr x))) と等価
(cdaar x)(cdr (car (car x))) と等価
(cdadr x)(cdr (car (cdr x))) と等価
(cdadr x)(cdr (car (cdr x))) と等価
(cddar x)(cdr (cdr (car x))) と等価
(cdddr x)(cdr (cdr (cdr x))) と等価
(caaaar x)(car (car (car (car x)))) と等価
(caaadr x)(car (car (car (cdr x)))) と等価
(caadar x)(car (car (cdr (car x)))) と等価
(caaddr x)(car (car (cdr (cdr x)))) と等価
(cadaar x)(car (cdr (car (car x)))) と等価
(cadadr x)(car (cdr (car (cdr x)))) と等価
(caddar x)(car (cdr (cdr (car x)))) と等価
(caddar x)(car (cdr (cdr (car x)))) と等価
(cadddr x)(car (cdr (cdr (cdr x)))) と等価
(cdaaar x)(cdr (car (car (car x)))) と等価
(cdaaar x)(cdr (car (car (car x)))) と等価
(cdaadr x)(cdr (car (car (cdr x)))) と等価
(cdaadr x)(cdr (car (car (cdr x)))) と等価
(cdadar x)(cdr (car (cdr (car x)))) と等価
(cdadar x)(cdr (car (cdr (car x)))) と等価
(cdaddr x)(cdr (car (cdr (cdr x)))) と等価
(cdaddr x)(cdr (car (cdr (cdr x)))) と等価
(cddaar x)(cdr (cdr (car (car x)))) と等価
(cddaar x)(cdr (cdr (car (car x)))) と等価
(cddadr x)(cdr (cdr (car (cdr x)))) と等価
(cddadr x)(cdr (cdr (car (cdr x)))) と等価
(cdddar x)(cdr (cdr (cdr (car x)))) と等価
(cdddar x)(cdr (cdr (cdr (car x)))) と等価
(cddddr x)(cdr (cdr (cdr (cdr x)))) と等価
(cddddr x)(cdr (cdr (cdr (cdr x)))) と等価

length(リスト長さ)

(length '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ 5

nth(番号による要素の参照)

Scheme言語の list-ref 関数の代替である。

(nth 0 '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ "Sapporo"
(nth 3 '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ "Osaka"

nthcdr(番号による後続リストの参照)

Scheme言語の list-tail 関数の代替である。

(nth 0 '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
(nth 3 '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ ("Osaka" "Fukuoka")

member、memq、memv (リストにその要素があるかどうかを判定)

第1引数で指定されたオブジェクトが第2引数で指定されたリストに含まれていれば、その最も左側の要素以降のリストを返す。オブジェクトの同一性の比較には、member 関数では equal 関数を、memq 関数では eq 関数を、memv 関数では eqv 関数を使う。

(member "Nagoya" '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ ("Nagoya" "Osaka" "Fukuoka")
(member "London" '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ nil

reverse

引数として指定されたリストと要素の順番が逆のリストを生成して返す。

(revese '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ ("Fukuoka" "Osaka" "Nagoya" "Tokyo" "Sapporo")

append (リストの非破壊的な連結)

(setq cities '("Sapporo" "Tokyo" "Naogya"))
(setq restCities '("Osaka" "Fukuoka"))
(append cities restCities)
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
cities
→ ("Sapporo" "Tokyo" "Naogya")

nconc (リストの破壊的な連結)

(nconc list1 list2) は (setcdr (last list1) list2) と等価である。
(nconc list1 list2 list3) は (nconc (nconc list1 list2) list3) と等価である。

(setq cities1 '("Sapporo" "Tokyo"))
(setq cities2 '("Nagoya"))
(setq cities3 '("Osaka" "Fukuoka"))
(nconc cities1 cities2 cities3)
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
cities1
→ ("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka")
cities2
→ ("Nagoya" "Osaka" "Fukuoka")

tconc (tconc 構造体が管理するリストの最後に要素を破壊的に追加する)

tconc 構造体は一つのリスト(★)を管理するたのデータ構造である。その実体は cons セルであり、car 部と cdr 部にはそれぞれ下表に示すセルが格納されている。

car 部管理対象リストの先頭セル ★
cdr 部管理対象リストの末尾セル (last ★)

下の例では tconc 構造体のセルの car 部と cdr 部を明示するためにドット記法で表記する。

; 初期化
(setq cities (tconc nil 要素1))
→ ((要素1) . (要素1))
; 最後に要素2を追加
(tconc cities 要素2))
→ ((要素1 要素2) . (要素2))
; 最後に要素3を追加
(tconc cities 要素2))
→ ((要素1 要素2 要素3) . (要素3))

sort

第1引数で与えられたリストを、第2引数で与えられた二項命題を満たすように並べ替える。この関数は破壊的であり、第1引数のリストの要素の cdr 部分は書き換えられてしまう。

; 数値の小さい順
(sort '(5.62 1.38 2.36 1.14 3.43) 'lessp)
→ (1.14 1.38 2.36 3.43 5.62)
; アルファベットの若い順
(sort '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka") 'alphalessp)
→ ("Fukuoka" "Nagoya" "Osaka" "Sapporo" "Tokyo")
; 既定の並び替えはアルファベットの若い順
(sort '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
→ ("Fukuoka" "Nagoya" "Osaka" "Sapporo" "Tokyo")
; 余弦値の小さい順(任意の比較関数を使う例)
(sort '(5.62 1.38 2.36 1.14 3.43) (lambda (a b) ((cos a) < (cos b))))
→ (3.43 2.36 1.38 1.14 5.62)
; 選択されたインスタンスのnameプロパティのアルファベットの若い順(任意の比較関数を使う例)
(sort (geGetSelectedSet) (lambda (a b) (alphalessp a~>name b~>name)))

sortcar

第1引数で与えられたリストを、各要素の car 部分の値が第2引数で与えられた二項命題を満たすような順序に並べ替える。この関数は破壊的であり、第1引数で与えられた cons セルとそれに続くすべての cons セルの cdr 部分は書き換えられてしまう。

(sortcar '((4.682 "Visual Basic") (19.043 "Java") (1.035 "Lua") (16.162 "C")) 'greaterp)
→ ((19.043 "Java") (16.162 "C") (4.682 "Visual Basic") (1.035 "Lua"))

apply (リストの値を引数として関数を実行する)

(setq trapeziumArea ; 台形の面積
  (lambda (a b h) (quotient (times (plus a b) h) 2.0))
)
(apply trapeziumArea (list 4.5 3.7 1.28))
→ 5.248
(apply 'strcat (list "Zyugemu" "Zyugemu" "Gokouno" "Surikire"))
→ "ZyugemuZyugemuGokounoSurikire"
(setq cities '("Sapporo" "Tokyo" "Nagoya" "Osaka" "Fukuoka"))
(define (toHtml values)
  (let ((buffer "<ul>"))
    (foreach v values
      (setq buffer (strcat buffer "<li>" v "</li>")))
    )
    (strcat buffer "</ul>")
  )
)
(define (toText values)
  (let ((buffer ""))
    (foreach v values
      (setq buffer (strcat buffer "* " v "\n")))
    )
    buffer
  )
)
(apply 'toHtml (list cities))
→ "<ul><li>Sapporo</li><li>Tokyo</li><li>Nagoya</li><li>Osaka</li><li>Fukuoka</li></ul>"
(apply 'toText (list cities))
→ "* Sapporo\n* Tokyo\n* Nagoya\n* Osaka\n* Fukuoka\n"

subst (要素の置換)

(setq greetings '(("Hello, " NAME ".") ("Guten Tag, " NAME ".") ("Bonjour, " NAME ".")))
(subst "Joseph" 'NAME greetings)
→ (("Hello, " "Joseph" ".") ("Guten Tag, " "Joseph" ".") ("Bonjour" "Joseph" "."))

*1 プロパーリストと呼ばれる