Scheme で非破壊的なリスト
頭の体操感覚でSchemeでリスト関係のライブラリを作ってみました。
すべて非破壊的になるようにしています。
グローバル変数も内部状態もありません。
引数も参照のみです。
深く考えずに作っているので、かなり怪しいです。
;------------------------------------------------------------------------------ ; リスト ; 非破壊的なリスト ; 引数のリストには副作用はない。 ; 引数チェックは行っていない。 ; リストの作成は '(A B C D) ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ; リストの要素を取得する。 ; (List_get '(A B C D) 2) => C ;------------------------------------------------------------------------------ (define (List_get list index) (cond ((= index 0) (car list)) (else (List_get (cdr list) (- index 1))) ) ) ;------------------------------------------------------------------------------ ; リストの要素数を返す。(length x)と同じ。 ; (List_count '(A B C D)) => 4 ;------------------------------------------------------------------------------ (define (List_count list) (cond ((null? list) 0) (else (+ 1 (List_count (cdr list)))) ) ) ;------------------------------------------------------------------------------ ; リストの指定したindexに値を置き換える。 ; 引数のlistは変わらない。 ; (List_set '(A B C D) 2 'g) => (A B g D) ;------------------------------------------------------------------------------ (define (List_set list index value) (cond ((= index 0) (cons value (cdr list))) (else (cons (car list) (List_set (cdr list) (- index 1) value))) ) ) ;------------------------------------------------------------------------------ ; リストの先頭に値を挿入する。(cons x list)と同じ。 ; 引数のlistは変わらない。 ; (List_addHead '(A B C D) 'g) => (g A B C D) ;------------------------------------------------------------------------------ (define (List_addHead list value) (cons value list)) ;------------------------------------------------------------------------------ ; リストの末尾に値を挿入する。 ; 引数のlistは変わらない。List_addHeadよりも重く、メモリを消費する。 ; (List_addTail '(A B C D) 'g) => (A B C D g) ; (List_addTail '() 'g) => (g) ;------------------------------------------------------------------------------ (define (List_addTail list value) (cond ((null? list) (cons value '())) (else (cons (car list) (List_addTail (cdr list) value))) ) ) ;------------------------------------------------------------------------------ ; リストの指定された位置に値を挿入する。 ; 引数のlistは変わらない。 ; (List_addAt '(A B C D) 2 'g) => (A B g C D) ; (List_addAt '(A B C D) 0 'g) => (g A B C D) ;------------------------------------------------------------------------------ (define (List_addAt list index value) (cond ((<= index 0) (List_addHead list value)) (else (cons (car list) (List_addAt (cdr list) (- index 1) value))))) ;------------------------------------------------------------------------------ ; 指定された位置の要素を削除する。 ; 引数のlistは変わらない。 ; (List_removeAt '(A B C D) 2) => (A B D) ;------------------------------------------------------------------------------ (define (List_removeAt list index) (cond ((= index 0) (cdr list)) (else (cons (car list) (List_removeAt (cdr list) (- index 1)))))) ;------------------------------------------------------------------------------ ; 指定された要素をindex個持つリストを作成する。 ; (List_create 3 'A) => (A A A) ;------------------------------------------------------------------------------ (define (List_create size value) (cond ((= size 0) '()) (else (cons value (List_create (- size 1) value))))) ;------------------------------------------------------------------------------ ; (List_zip '(A B C D) '(a b c d)) => ((A a) (B b) (C c) (D d)) ;------------------------------------------------------------------------------ (define (List_zip list1 list2) (cond ((or (null? list1) (null? list2)) '()) (else (cons (list (car list1) (car list2)) (List_zip (cdr list1) (cdr list2)))))) ;------------------------------------------------------------------------------ ; 等差数列を作成する。 ; (List_createArithmeticalProgression 1 2 5) => (1 3 5 7 9) ; (List_createArithmeticalProgression 1 -2 5) => (1 -1 -3 -5 -7) ; (List_createArithmeticalProgression 1 0 5) => (1 1 1 1 1) ;------------------------------------------------------------------------------ (define (List_createArithmeticalProgression init delta count) (cond ((= count 0) '()) (else (cons init (List_createArithmeticalProgression (+ init delta) delta (- count 1)))))) ;------------------------------------------------------------------------------ ; ツリー構造のリストを階層のないリストにする。 ; (List_flat '(((A B) C) (D E))) => (A B C D E) ;------------------------------------------------------------------------------ (define (List_flat l) (cond ((null? l) '()) ((not (list? l)) (list l)) (else (append (List_flat (car l)) (List_flat (cdr l)))))) ;------------------------------------------------------------------------------ (define (List_test) (list (equal? (List_get '(A B C D) 2) 'C) (equal? (List_count '(A B C D)) 4) (equal? (List_set '(A B C D) 2 'g) '(A B g D)) (equal? (List_addHead '(A B C D) 'g) '(g A B C D)) (equal? (List_addTail '(A B C D) 'g) '(A B C D g)) (equal? (List_addTail '() 'g) '(g)) (equal? (List_addAt '(A B C D) 2 'g) '(A B g C D)) (equal? (List_addAt '(A B C D) 0 'g) '(g A B C D)) (equal? (List_removeAt '(A B C D) 2) '(A B D)) (equal? (List_create 3 'A) '(A A A)) (equal? (List_zip '(A B C D) '(a b c d)) '((A a) (B b) (C c) (D d))) (equal? (List_flat '()) '()) (equal? (List_flat '((((A))))) '(A)) (equal? (List_flat '(((A B) C) (D E))) '(A B C D E)) ) )