페어와 리스트
페어와 리스트 (Pairs and Lists)
페어(pair)는 정확히 두 값을 묶는 데이터 구조예요. 그리고 리스트(list)는 페어를 재귀적으로 이어 붙인 구조라서, Racket에서 아주 흔하게 쓰여요. 이 절에서는 페어와 리스트를 만들고, 다루고, 탐색하고, 변환하는 수많은 함수들을 차례대로 살펴볼게요.
출처: Racket Reference
본문
Racket Guide의 Pairs and Lists에서 페어와 리스트를 소개해요.
페어는 정확히 두 값을 결합해요. 첫 번째 값은 car 프로시저로 접근하고, 두 번째 값은 cdr 프로시저로 접근해요. 페어는 가변적이지 않아요(단, Mutable Pairs and Lists 참고).
리스트는 재귀적으로 정의돼요: 상수 null이거나, 두 번째 값이 리스트인 페어예요.
리스트는 단일 값 시퀀스로 사용될 수 있어요(Sequences 참고). 리스트의 원소들이 시퀀스의 원소 역할을 해요. in-list도 참고하세요.
순환 데이터 구조는 read나 make-reader-graph를 사용해 불변 페어만으로도 만들 수 있어요. 페어에서 시작해 어떤 수의 cdr를 사용해 다시 시작 페어로 돌아온다면, 그 페어는 리스트가 아니에요.
페어·리스트를 읽는 방법은 Reading Pairs and Lists를, 출력하는 방법은 Printing Pairs and Lists를 참고하세요.
4.10.1 페어 생성자와 선택자 (Pair Constructors and Selectors)
procedure
(pair? v) → boolean?
v : any/c
v가 페어면 #t를, 그렇지 않으면 #f를 돌려줘요.
Examples:
> (pair? 1)
#f
> (pair? (cons 1 2))
#t
> (pair? (list 1 2))
#t
> (pair? '(1 2))
#t
> (pair? '())
#f
procedure
(null? v) → boolean?
v : any/c
v가 빈 리스트면 #t를, 그렇지 않으면 #f를 돌려줘요.
Examples:
> (null? 1)
#f
> (null? '(1 2))
#f
> (null? '())
#t
> (null? (cdr (list 1)))
#t
procedure
(cons a d) → list?
a : any/c
d : list?
(cons a d) → pair?
a : any/c
d : any/c
첫 번째 원소가 a이고 두 번째 원소가 d인 새로 할당된 페어를 돌려줘요. d가 리스트일 때 할당된 페어도 리스트예요.
Examples:
> (cons 1 2)
'(1 . 2)
> (cons 1 '())
'(1)
procedure
(car p) → any/c
p : pair?
페어 p의 첫 번째 원소를 돌려줘요.
Examples:
> (car '(1 2))
1
> (car '(2 . 3))
2
procedure
(cdr p) → any/c
p : pair?
페어 p의 두 번째 원소를 돌려줘요.
Examples:
> (cdr '(1 2))
'(2)
> (cdr '(2 . 3))
3
value
null : null?
빈 리스트예요.
Examples:
> null
'()
> '()
'()
> (eq? '() null)
#t
procedure
(list? v) → boolean?
v : any/c
v가 리스트면(빈 리스트이거나, 두 번째 원소가 리스트인 페어) #t를, 그렇지 않으면 #f를 돌려줘요. 이 프로시저는 내부 캐싱 덕분에 사실상 상수 시간이 걸려요(그래서 필요한 페어 순회는 원칙적으로 페어 할당의 추가 비용으로 간주될 수 있어요).
Examples:
> (list? '(1 2))
#t
> (list? (cons 1 (cons 2 '())))
#t
> (list? (cons 1 2))
#f
procedure
(list v ...) → list?
v : any/c
vs를 원소로 담는 새로 할당된 리스트를 돌려줘요.
Examples:
> (list 1 2 3 4)
'(1 2 3 4)
> (list (list 1 2) (list 3 4))
'((1 2) (3 4))
procedure
(list* v ... tail) → list?
v : any/c
tail : list?
(list* v ... tail) → any/c
v : any/c
tail : any/c
list와 같지만 마지막 인자가 결과의 마지막 원소 대신 꼬리로 사용돼요. 마지막 인자가 리스트일 때만 결과가 리스트예요.
Examples:
> (list* 1 2 3)
'(1 2 . 3)
> (list* 1 2 (list 3 4))
'(1 2 3 4)
procedure
(build-list n proc) → list?
n : exact-nonnegative-integer?
proc : (exact-nonnegative-integer? . -> . any/c)
0부터 (sub1 n)까지의 정수에 proc을 순서대로 적용해 n개의 원소를 가진 리스트를 만들어요. 결과 리스트를 lst라 하면 (list-ref lst i)는 (proc i)가 만든 값이에요.
Examples:
> (build-list 10 values)
'(0 1 2 3 4 5 6 7 8 9)
> (build-list 5 (lambda (x) (* x x)))
'(0 1 4 9 16)
4.10.2 리스트 연산 (List Operations)
procedure
(length lst) → exact-nonnegative-integer?
lst : list?
lst의 원소 수를 돌려줘요. 이 함수는 그 길이에 비례하는 시간이 걸려요.
Examples:
> (length (list 1 2 3 4))
4
> (length '())
0
procedure
(list-ref lst pos) → any/c
lst : list?
pos : exact-nonnegative-integer?
(list-ref lst pos) → any/c
lst : pair?
pos : exact-nonnegative-integer?
lst의 pos 위치의 원소를 돌려줘요(리스트의 첫 원소는 위치 0). 리스트에 pos개 이하의 원소가 있으면 exn:fail:contract 예외가 발생해요.
lst 인자는 실제로 리스트일 필요 없어요. lst는 단지 적어도 (add1 pos)개의 페어로 이뤄진 연결 고리로 시작하기만 하면 돼요.
이 함수는 pos에 비례하는 시간이 걸려요.
Examples:
> (list-ref (list 'a 'b 'c) 0)
'a
> (list-ref (list 'a 'b 'c) 1)
'b
> (list-ref (list 'a 'b 'c) 2)
'c
> (list-ref (cons 1 2) 0)
1
> (list-ref (cons 1 2) 1)
list-ref: index reaches a non-pair
index: 1
in: '(1 . 2)
procedure
(list-tail lst pos) → list?
lst : list?
pos : exact-nonnegative-integer?
(list-tail lst pos) → any/c
lst : any/c
pos : exact-nonnegative-integer?
lst의 첫 pos개 원소 뒤의 리스트를 돌려줘요. 리스트에 pos개 미만의 원소가 있으면 exn:fail:contract 예외가 발생해요.
lst 인자는 실제로 리스트일 필요 없어요. lst는 단지 적어도 pos개의 페어로 이뤄진 연결 고리로 시작하기만 하면 돼요.
이 함수는 pos에 비례하는 시간이 걸려요.
Examples:
> (list-tail (list 1 2 3 4 5) 2)
'(3 4 5)
> (list-tail (cons 1 2) 1)
2
> (list-tail (cons 1 2) 2)
list-tail: index reaches a non-pair
index: 2
in: '(1 . 2)
> (list-tail 'not-a-pair 0)
'not-a-pair
procedure
(append lst ...) → list?
lst : list?
(append lst ... v) → any/c
lst : list?
v : any/c
모든 인자가 리스트일 때, 결과는 주어진 리스트들의 모든 원소를 순서대로 담은 리스트예요. 마지막 인자는 결과의 꼬리에 직접 사용돼요.
마지막 인자는 리스트일 필요가 없으며, 그 경우 결과는 "부적절 리스트(improper list)"예요.
이 함수는 마지막 인자를 제외한 모든 인자의 길이(합산해서)에 비례하는 시간이 걸려요.
Examples:
> (append (list 1 2) (list 3 4))
'(1 2 3 4)
> (append (list 1 2) (list 3 4) (list 5 6) (list 7 8))
'(1 2 3 4 5 6 7 8)
procedure
(reverse lst) → list?
lst : list?
lst와 같은 원소를 역순으로 가진 리스트를 돌려줘요.
이 함수는 lst의 길이에 비례하는 시간이 걸려요.
Example:
> (reverse (list 1 2 3 4))
'(4 3 2 1)
4.10.3 리스트 반복 (List Iteration)
procedure
(map proc lst ...+) → list?
proc : procedure?
lst : list?
lsts의 첫 원소부터 마지막 원소까지 proc을 적용해요. proc 인자는 제공된 lsts의 개수와 같은 수의 인자를 받아야 하고, 모든 lsts는 같은 원소 수를 가져야 해요. 결과는 proc의 각 결과를 순서대로 담은 리스트예요.
Examples:
> (map (lambda (number)
(+ 1 number))
'(1 2 3 4))
'(2 3 4 5)
> (map (lambda (number1 number2)
(+ number1 number2))
'(1 2 3 4)
'(10 100 1000 10000))
'(11 102 1003 10004)
procedure
(andmap proc lst ...+) → any
proc : procedure?
lst : list?
proc이 lst의 각 원소에 적용된다는 점에서 map과 비슷하지만,
andmap 함수는 실제로는 리스트를 만들지 않으므로 map보다 foldl에 더 가까워요. 그래도 (andmap f (list x y z))는 (map f (list x y z))가 (list (f x) (f y) (f z))와 동등한 것과 같은 방식으로 (and (f x) (f y) (f z))와 동등해요.
-
proc의 어떤 적용이#f를 만들면 결과는#f예요. 그 경우proc은lsts의 이후 원소들에는 적용되지 않아요. 그리고 -
결과는
lsts의 마지막 원소에proc을 적용한 결과예요. 더 정확히는lsts의 마지막 원소에proc을 적용하는 것이andmap호출에 대해 꼬리 위치에 있어요.
lsts가 비어 있으면 #t가 돌아와요.
Examples:
> (andmap positive? '(1 2 3))
#t
> (andmap positive? '(1 2 a))
positive?: contract violation
expected: real?
given: 'a
> (andmap positive? '(1 -2 a))
#f
> (andmap + '(1 2 3) '(4 5 6))
9
procedure
(ormap proc lst ...+) → any
proc : procedure?
lst : list?
proc이 lst의 각 원소에 적용된다는 점에서 map과 비슷하지만,
위의 andmap 내용을 이어서, (ormap f (list x y z))는 (or (f x) (f y) (f z))와 동등해요.
-
proc의 모든 적용이#f를 만들면 결과는#f예요. 그리고 -
결과는
#f가 아닌 값을 만드는proc의 첫 적용의 결과예요. 그 경우proc은lsts의 이후 원소들에는 적용되지 않아요.lsts의 마지막 원소에proc을 적용하는 것은ormap호출에 대해 꼬리 위치에 있어요.
lsts가 비어 있으면 #f가 돌아와요.
Examples:
> (ormap eq? '(a b c) '(a b c))
#t
> (ormap positive? '(1 2 a))
#t
> (ormap + '(1 2 3) '(4 5 6))
5
procedure
(for-each proc lst ...+) → void?
proc : procedure?
lst : list?
map과 비슷하지만 proc은 그 효과만을 위해 호출되고, 그 결과(몇 개의 값이든)는 무시돼요.
Example:
> (for-each (lambda (arg)
(printf "Got ~a\n" arg)
23)
'(1 2 3 4))
Got 1
Got 2
Got 3
Got 4
procedure
(foldl proc init lst ...+) → any/c
proc : procedure?
init : any/c
lst : list?
map처럼 foldl은 하나 이상의 리스트의 원소에 프로시저를 적용해요. map이 반환 값을 리스트로 결합하는 반면, foldl은 proc이 결정하는 임의의 방식으로 반환 값을 결합해요.
foldl이 n개의 리스트로 호출되면 proc은 n+1개의 인자를 받아야 해요. 추가 인자는 지금까지 결합된 반환 값이에요. proc은 처음에 각 리스트의 첫 항목과 함께 호출되고, 마지막 인자는 init이에요. 이후의 proc 호출에서 마지막 인자는 이전 proc 호출의 반환 값이에요. 입력 lsts는 왼쪽에서 오른쪽으로 순회되고, 전체 foldl 적용의 결과는 마지막 proc 적용의 결과예요. lsts가 비어 있으면 결과는 init이에요.
foldr과 달리 foldl은 lsts를 상수 공간에서 처리해요(각 proc 호출을 위한 공간은 별도).
Examples:
> (foldl (lambda (a b result)
(* result (- a b)))
1
'(1 2 3)
'(4 5 6))
-27
procedure
(foldr proc init lst ...+) → any/c
proc : procedure?
init : any/c
lst : list?
foldl과 같지만 리스트를 오른쪽에서 왼쪽으로 순회해요. foldl과 달리 foldr은 lsts를 그 길이에 비례하는 공간에서 처리해요(각 proc 호출을 위한 공간은 별도).
Examples:
> (foldr cons '() '(1 2 3 4))
'(1 2 3 4)
> (foldr (lambda (v l) (cons (add1 v) l)) '() '(1 2 3 4))
'(2 3 4 5)
4.10.4 더 많은 리스트 반복 (More List Iteration)
(require racket/list/iteration)
package: sequence-tools-lib
이 절에서 다루는 바인딩들은 racket/base나 racket이 아니라 racket/list/iteration 라이브러리에서 제공돼요.
이 절의 바인딩들은 기본 시퀀스 라이브러리의 확장 역할을 하는 sequence-tools-lib 패키지에서 제공돼요.
procedure
(running-foldl proc init lst ...+) → list?
proc : procedure?
init : any/c
lst : list?
foldl과 같지만 초기 누산기뿐만 아니라 proc을 적용한 모든 결과를 담은 리스트를 만들어요.
Examples:
> (running-foldl (lambda (a b acc)
(* acc (+ a b)))
1
'(1 2)
'(3 4))
'(1 4 24)
procedure
(running-foldr proc init lst ...+) → list?
proc : procedure?
init : any/c
lst : list?
running-foldl과 같지만 foldr처럼 오른쪽에서 중간 결과를 만들어요.
Examples:
> (running-foldr (lambda (a b acc)
(* acc (+ a b)))
1
'(1 2)
'(3 4))
'(24 6 1)
4.10.5 리스트 필터링 (List Filtering)
procedure
(filter pred lst) → list?
pred : procedure?
lst : list?
pred가 참 값을 만드는 lst의 원소들로만 이뤄진 리스트를 돌려줘요. pred 프로시저는 첫 번째부터 마지막까지 각 원소에 적용돼요.
Example:
> (filter positive? '(1 -2 3 4 -5))
'(1 3 4)
procedure
(remove v lst [proc]) → list?
v : any/c
lst : list?
proc : procedure? = equal?
비교 프로시저 proc(두 인자를 받아야 함)을 사용해 v와 같은 lst의 첫 원소를 생략한, lst와 같은 리스트를 돌려줘요. v를 첫 인자로, lst의 한 원소를 두 번째 인자로 사용해요. (proc에 따르면) lst에 v와 같은 원소가 없으면 lst가 변경 없이 돌아와요.
Examples:
> (remove 2 (list 1 2 3 2 4))
'(1 3 2 4)
> (remove '(2) (list '(1) '(2) '(3)))
'((1) (3))
> (remove "2" (list "1" "2" "3"))
'("1" "3")
> (remove #\c (list #\a #\b #\c))
'(#\a #\b)
> (remove "B" (list "a" "A" "b" "B") string-ci=?)
'("a" "A" "B")
> (remove 5 (list 1 2 3 2 4))
'(1 2 3 2 4)
base 패키지의 8.2.0.2 버전에서 제거가 발생하지 않으면 출력이 lst에 eq?임을 보장하도록 변경했어요.
procedure
(remq v lst) → list?
v : any/c
lst : list?
(remove v lst eq?)를 돌려줘요.
Examples:
> (remq 2 (list 1 2 3 4 5))
'(1 3 4 5)
> (remq '(2) (list '(1) '(2) '(3)))
'((1) (2) (3))
> (remq "2" (list "1" "2" "3"))
'("1" "3")
> (remq #\c (list #\a #\b #\c))
'(#\a #\b)
procedure
(remv v lst) → list?
v : any/c
lst : list?
(remove v lst eqv?)를 돌려줘요.
Examples:
> (remv 2 (list 1 2 3 4 5))
'(1 3 4 5)
> (remv '(2) (list '(1) '(2) '(3)))
'((1) (2) (3))
> (remv "2" (list "1" "2" "3"))
'("1" "3")
> (remv #\c (list #\a #\b #\c))
'(#\a #\b)
procedure
(remw v lst) → list?
v : any/c
lst : list?
(remove v lst equal-always?)를 돌려줘요.
Examples:
> (remw 2 (list 1 2 3 4 5))
'(1 3 4 5)
> (remw '(2) (list '(1) '(2) '(3)))
'((1) (3))
> (remw "2" (list "1" "2" "3"))
'("1" "3")
> (remw #\c (list #\a #\b #\c))
'(#\a #\b)
> (define b1 (box 5))
> (define b2 (box 5))
> (remw b2 (list 0 b1 1 b2 2))
'(0 #&5 1 2)
base 패키지의 8.5.0.3 버전에서 추가됐어요.
procedure
(remove* v-lst lst [proc]) → list?
v-lst : list?
lst : list?
proc : procedure? = equal?
remove와 같지만 v-lst의 각 원소의 모든 인스턴스를 lst에서 제거해요.
Example:
> (remove* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
base 패키지의 8.2.0.2 버전에서 제거가 발생하지 않으면 출력이 lst에 eq?임을 보장하도록 변경했어요.
procedure
(remq* v-lst lst) → list?
v-lst : list?
lst : list?
(remove* v-lst lst eq?)를 돌려줘요.
Example:
> (remq* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
procedure
(remv* v-lst lst) → list?
v-lst : list?
lst : list?
(remove* v-lst lst eqv?)를 돌려줘요.
Example:
> (remv* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
procedure
(remw* v-lst lst) → list?
v-lst : list?
lst : list?
(remove* v-lst lst equal-always?)를 돌려줘요.
Examples:
> (remw* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
> (define b1 (box 5))
> (define b2 (box 5))
> (remw* (list b2) (list 0 b1 1 b2 2 b2 3))
'(0 #&5 1 2 3)
base 패키지의 8.5.0.3 버전에서 추가됐어요.
procedure
(sort lst less-than? [#:key extract-key #:cache-keys? cache-keys?]) → list?
lst : list?
less-than? : (any/c any/c . -> . any/c)
extract-key : (or/c #f (any/c . -> . any/c)) = #f
cache-keys? : boolean? = #f
less-than? 프로시저에 따라 정렬된 리스트를 돌려줘요. 이 프로시저는 lst의 두 원소를 받아, 첫 번째가 두 번째보다 작으면(즉 더 일찍 정렬되어야 하면) 참 값을 돌려줘요.
정렬은 안정적(stable)이에요. lst의 두 원소가 "같으면"(즉 less-than?가 어떤 순서로 주어도 참 값을 돌려주지 않으면) 원소들은 출력 리스트에서 lst에서의 상대적 순서를 유지해요. 이 보장을 지키려면 sort를 엄격한 비교 함수(예: < 또는 string<?, <=나 string<=?는 안 됨)와 함께 사용해요.
IEEE-754 숫자 체계가 +nan.0을 다른 어떤 숫자보다 크지도 작지도 같지도 않게 규정한다는 특이한 사실 때문에, 이 값을 포함한 리스트를 정렬하면 놀라운 결과가 나올 수 있어요.
#:key 인자 extract-key는 각 리스트 원소에서 비교할 키 값을 추출하는 데 사용되며, #f는 (lambda (x) x)로 대체돼요. 즉 전체 비교 프로시저는 본질적으로 다음과 같아요:
(lambda (x y)
(less-than? (extract-key x) (extract-key y)))
기본적으로 extract-key는 모든 비교에 대해 두 리스트 원소에 적용되지만, cache-keys?가 참이면 extract-key 함수는 각 리스트 항목에 정확히 한 번만 사용돼요. extract-key가 비싼 연산일 때 cache-keys?에 참 값을 제공해요. 예를 들어 file-or-directory-modify-seconds를 사용해 리스트의 모든 파일에 대한 타임스탬프를 추출한다면 파일 시스템 호출을 최소화하기 위해 cache-keys?를 #t로 해야 하지만, extract-key가 car라면 cache-keys?는 #f여야 해요. 또 다른 예로 extract-key를 (lambda (x) (random))로, cache-keys?를 #t로 제공하면 효과적으로 리스트를 섞어요.
Examples:
> (sort '(("aardvark") ("dingo") ("cow") ("bear"))
#:key car string<?)
'(("aardvark") ("bear") ("cow") ("dingo"))
4.10.6 리스트 탐색 (List Searching)
procedure
(member v lst [is-equal?]) → (or/c #f list?)
v : any/c
lst : list?
is-equal? : (any/c any/c . -> . any/c) = equal?
(member v lst [is-equal?]) → any/c
v : any/c
lst : any/c
is-equal? : (any/c any/c . -> . any/c) = equal?
is-equal?에 따라 v와 동일한 lst의 첫 원소를 찾아요. 그런 원소가 있으면 그 원소로 시작하는 lst의 꼬리를 돌려줘요. 그렇지 않으면 결과는 #f예요.
lst 인자는 실제로 리스트일 필요 없어요. lst는 일치하는 원소를 찾을 때까지 페어의 연결 고리로 시작하기만 하면 돼요. 일치하는 원소를 찾지 못하면 lst는 리스트(그리고 순환 리스트가 아닌)여야 해요. 원소가 발견되고 돌려주는 lst의 꼬리가 리스트가 아닌 경우 결과는 리스트가 아닐 수 있어요.
Examples:
> (member 2 (list 1 2 3 4))
'(2 3 4)
> (member 9 (list 1 2 3 4))
#f
> (member #'x (list #'x #'y) free-identifier=?)
'(#<syntax:eval:576:0 x> #<syntax:eval:576:0 y>)
> (member #'a (list #'x #'y) free-identifier=?)
#f
> (member 'b '(a b . etc))
'(b . etc)
> (member 'c '(a b . etc))
member: not a proper list
in: '(a b . etc)
procedure
(memw v lst) → (or/c #f list?)
v : any/c
lst : list?
(memw v lst) → any/c
v : any/c
lst : any/c
member와 같지만 equal-always?를 사용해 원소를 찾아요.
Examples:
> (memw 2 (list 1 2 3 4))
'(2 3 4)
> (memw 9 (list 1 2 3 4))
#f
> (define b1 (box 5))
> (define b2 (box 5))
> (memw b2 (list 0 b1 1 b2 2))
'(#&5 2)
base 패키지의 8.5.0.3 버전에서 추가됐어요.
procedure
(memv v lst) → (or/c #f list?)
v : any/c
lst : list?
(memv v lst) → any/c
v : any/c
lst : any/c
member와 같지만 eqv?를 사용해 원소를 찾아요.
Examples:
> (memv 2 (list 1 2 3 4))
'(2 3 4)
> (memv 9 (list 1 2 3 4))
#f
procedure
(memq v lst) → (or/c #f list?)
v : any/c
lst : list?
(memq v lst) → any/c
v : any/c
lst : any/c
member와 같지만 eq?를 사용해 원소를 찾아요.
Examples:
> (memq 2 (list 1 2 3 4))
'(2 3 4)
> (memq 9 (list 1 2 3 4))
#f
procedure
(memf proc lst) → (or/c #f list?)
proc : procedure?
lst : list?
(memf proc lst) → any/c
proc : procedure?
lst : any/c
member와 같지만 술어 proc을 사용해 원소를 찾아요. proc을 원소에 적용해 참 값을 돌려주면 원소가 발견된 거예요.
Example:
> (memf (lambda (arg)
(> arg 9))
'(7 8 9 10 11))
'(10 11)
procedure
(findf proc lst) → (or/c #f any/c)
proc : procedure?
lst : list?
(findf proc lst) → any/c
proc : procedure?
lst : any/c
memf와 같지만 lst의 꼬리나 #f 대신 원소나 #f를 돌려줘요.
특히 lst의 원소가 #f라면 #f의 결과는 모호할 수 있어요: 어떤 원소도 proc을 만족하지 않는다는 뜻일 수도 있고, 원소 #f가 proc을 만족한다는 뜻일 수도 있어요.
Example:
> (findf (lambda (arg)
(> arg 9))
'(7 8 9 10 11))
10
procedure
(assoc v lst [is-equal?]) → (or/c pair? #f)
v : any/c
lst : (listof pair?)
is-equal? : (any/c any/c . -> . any/c) = equal?
(assoc v lst [is-equal?]) → pair?
v : any/c
lst : (list*of pair? (not/c '()))
is-equal? : (any/c any/c . -> . any/c) = equal?
is-equal?에 따라 car가 v와 동일한 lst의 첫 원소를 찾아요. 그런 원소가 있으면 그 페어(즉 lst의 한 원소)가 돌아와요. 그렇지 않으면 결과는 #f예요.
lst 인자는 실제로 페어의 리스트일 필요 없어요. lst는 일치하는 원소를 찾을 때까지 페어를 포함한 페어의 연결 고리로 시작하기만 하면 돼요. 일치하는 원소를 찾지 못하면 lst는 페어의 리스트(그리고 순환 리스트가 아닌)여야 해요.
Examples:
> (assoc 3.5
(list (list 1 2) (list 3 4) (list 5 6))
(lambda (a b) (< (abs (- a b)) 1)))
'(3 4)
procedure
(assw v lst) → (or/c pair? #f)
v : any/c
lst : (listof pair?)
(assw v lst) → pair?
v : any/c
lst : (list*of pair? (not/c '()))
assoc와 같지만 equal-always?를 사용해 원소를 찾아요.
Examples:
> (assw 3 (list (list 1 2) (list 3 4) (list 5 6)))
'(3 4)
> (define b1 (box 0))
> (define b2 (box 0))
> (assw b2 (list (cons b1 1) (cons b2 2)))
'(#&0 . 2)
base 패키지의 8.5.0.3 버전에서 추가됐어요.
procedure
(assv v lst) → (or/c pair? #f)
v : any/c
lst : (listof pair?)
(assv v lst) → pair?
v : any/c
lst : (list*of pair? (not/c '()))
assoc와 같지만 eqv?를 사용해 원소를 찾아요.
Example:
> (assv 3 (list (list 1 2) (list 3 4) (list 5 6)))
'(3 4)
procedure
(assq v lst) → (or/c pair? #f)
v : any/c
lst : (listof pair?)
(assq v lst) → pair?
v : any/c
lst : (list*of pair? (not/c '()))
assoc와 같지만 eq?를 사용해 원소를 찾아요.
Example:
> (assq 'c (list (list 'a 'b) (list 'c 'd) (list 'e 'f)))
'(c d)
procedure
(assf proc lst) → (or/c pair? #f)
proc : procedure?
lst : (listof pair?)
(assf proc lst) → pair?
proc : procedure?
lst : (list*of pair? (not/c '()))
assoc와 같지만 술어 proc을 사용해 원소를 찾아요. proc을 lst 원소의 car에 적용해 참 값을 돌려주면 원소가 발견된 거예요.
Example:
> (assf (lambda (arg)
(> arg 2))
(list (list 1 2) (list 3 4) (list 5 6)))
'(3 4)
4.10.7 페어 접근자 약칭 (Pair Accessor Shorthands)
이 절의 각 함수는 car와 cdr의 조합을 편하게 쓰기 위한 약칭이에요. 이름 속의 a는 car를, d는 cdr를 나타내요(오른쪽에서 왼쪽으로 읽어요). 예를 들어 caadr은 (car (car (cdr v)))예요.
procedure
(caar v) → any/c
v : (cons/c pair? any/c)
(car (car v))를 돌려줘요.
Example:
> (caar '((1 2) 3 4))
1
procedure
(cadr v) → any/c
v : (cons/c any/c pair?)
(car (cdr v))를 돌려줘요.
Example:
> (cadr '((1 2) 3 4))
3
procedure
(cdar v) → any/c
v : (cons/c pair? any/c)
(cdr (car v))를 돌려줘요.
Example:
> (cdar '((7 6 5 4 3 2 1) 8 9))
'(6 5 4 3 2 1)
procedure
(cddr v) → any/c
v : (cons/c any/c pair?)
(cdr (cdr v))를 돌려줘요.
Example:
> (cddr '(2 1))
'()
procedure
(caaar v) → any/c
v : (cons/c (cons/c pair? any/c) any/c)
(car (car (car v)))를 돌려줘요.
Example:
> (caaar '(((6 5 4 3 2 1) 7) 8 9))
6
procedure
(caadr v) → any/c
v : (cons/c any/c (cons/c pair? any/c))
(car (car (cdr v)))를 돌려줘요.
Example:
> (caadr '(9 (7 6 5 4 3 2 1) 8))
7
procedure
(cadar v) → any/c
v : (cons/c (cons/c any/c pair?) any/c)
(car (cdr (car v)))를 돌려줘요.
Example:
> (cadar '((7 6 5 4 3 2 1) 8 9))
6
procedure
(caddr v) → any/c
v : (cons/c any/c (cons/c any/c pair?))
(car (cdr (cdr v)))를 돌려줘요.
Example:
> (caddr '(3 2 1))
1
procedure
(cdaar v) → any/c
v : (cons/c (cons/c pair? any/c) any/c)
(cdr (car (car v)))를 돌려줘요.
Example:
> (cdaar '(((6 5 4 3 2 1) 7) 8 9))
'(5 4 3 2 1)
procedure
(cdadr v) → any/c
v : (cons/c any/c (cons/c pair? any/c))
(cdr (car (cdr v)))를 돌려줘요.
Example:
> (cdadr '(9 (7 6 5 4 3 2 1) 8))
'(6 5 4 3 2 1)
procedure
(cddar v) → any/c
v : (cons/c (cons/c any/c pair?) any/c)
(cdr (cdr (car v)))를 돌려줘요.
Example:
> (cddar '((7 6 5 4 3 2 1) 8 9))
'(5 4 3 2 1)
procedure
(cdddr v) → any/c
v : (cons/c any/c (cons/c any/c pair?))
(cdr (cdr (cdr v)))를 돌려줘요.
Example:
> (cdddr '(3 2 1))
'()
procedure
(caaaar v) → any/c
v : (cons/c (cons/c (cons/c pair? any/c) any/c) any/c)
(car (car (car (car v))))를 돌려줘요.
Example:
> (caaaar '((((5 4 3 2 1) 6) 7) 8 9))
5
procedure
(caaadr v) → any/c
v : (cons/c any/c (cons/c (cons/c pair? any/c) any/c))
(car (car (car (cdr v))))를 돌려줘요.
Example:
> (caaadr '(9 ((6 5 4 3 2 1) 7) 8))
6
procedure
(caadar v) → any/c
v : (cons/c (cons/c any/c (cons/c pair? any/c)) any/c)
(car (car (cdr (car v))))를 돌려줘요.
Example:
> (caadar '((7 (5 4 3 2 1) 6) 8 9))
5
procedure
(caaddr v) → any/c
v : (cons/c any/c (cons/c any/c (cons/c pair? any/c)))
(car (car (cdr (cdr v))))를 돌려줘요.
Example:
> (caaddr '(9 8 (6 5 4 3 2 1) 7))
6
procedure
(cadaar v) → any/c
v : (cons/c (cons/c (cons/c any/c pair?) any/c) any/c)
(car (cdr (car (car v))))를 돌려줘요.
Example:
> (cadaar '(((6 5 4 3 2 1) 7) 8 9))
5
procedure
(cadadr v) → any/c
v : (cons/c any/c (cons/c (cons/c any/c pair?) any/c))
(car (cdr (car (cdr v))))를 돌려줘요.
Example:
> (cadadr '(9 (7 6 5 4 3 2 1) 8))
6
procedure
(caddar v) → any/c
v : (cons/c (cons/c any/c (cons/c any/c pair?)) any/c)
(car (cdr (cdr (car v))))를 돌려줘요.
Example:
> (caddar '((7 6 5 4 3 2 1) 8 9))
5
procedure
(cadddr v) → any/c
v : (cons/c any/c (cons/c any/c (cons/c any/c pair?)))
(car (cdr (cdr (cdr v))))를 돌려줘요.
Example:
> (cadddr '(4 3 2 1))
1
procedure
(cdaaar v) → any/c
v : (cons/c (cons/c (cons/c pair? any/c) any/c) any/c)
(cdr (car (car (car v))))를 돌려줘요.
Example:
> (cdaaar '((((5 4 3 2 1) 6) 7) 8 9))
'(4 3 2 1)
procedure
(cdaadr v) → any/c
v : (cons/c any/c (cons/c (cons/c pair? any/c) any/c))
(cdr (car (car (cdr v))))를 돌려줘요.
Example:
> (cdaadr '(9 ((6 5 4 3 2 1) 7) 8))
'(5 4 3 2 1)
procedure
(cdadar v) → any/c
v : (cons/c (cons/c any/c (cons/c pair? any/c)) any/c)
(cdr (car (cdr (car v))))를 돌려줘요.
Example:
> (cdadar '((7 (5 4 3 2 1) 6) 8 9))
'(4 3 2 1)
procedure
(cdaddr v) → any/c
v : (cons/c any/c (cons/c any/c (cons/c pair? any/c)))
(cdr (car (cdr (cdr v))))를 돌려줘요.
Example:
> (cdaddr '(9 8 (6 5 4 3 2 1) 7))
'(5 4 3 2 1)
procedure
(cddaar v) → any/c
v : (cons/c (cons/c (cons/c any/c pair?) any/c) any/c)
(cdr (cdr (car (car v))))를 돌려줘요.
Example:
> (cddaar '(((6 5 4 3 2 1) 7) 8 9))
'(4 3 2 1)
procedure
(cddadr v) → any/c
v : (cons/c any/c (cons/c (cons/c any/c pair?) any/c))
(cdr (cdr (car (cdr v))))를 돌려줘요.
Example:
> (cddadr '(9 (7 6 5 4 3 2 1) 8))
'(5 4 3 2 1)
procedure
(cdddar v) → any/c
v : (cons/c (cons/c any/c (cons/c any/c pair?)) any/c)
(cdr (cdr (cdr (car v))))를 돌려줘요.
Example:
> (cdddar '((7 6 5 4 3 2 1) 8 9))
'(4 3 2 1)
procedure
(cddddr v) → any/c
v : (cons/c any/c (cons/c any/c (cons/c any/c pair?)))
(cdr (cdr (cdr (cdr v))))를 돌려줘요.
Example:
> (cddddr '(4 3 2 1))
'()
4.10.8 추가 리스트 함수와 동의어 (Additional List Functions and Synonyms)
(require racket/list)
package: base
이 절에서 다루는 바인딩들은 racket/base가 아닌 racket/list와 racket 라이브러리에서 제공돼요.
value
empty : null?
빈 리스트예요.
Examples:
> empty
'()
> (eq? empty null)
#t
procedure
(cons? v) → boolean?
v : any/c
(pair? v)와 같아요.
Example:
> (cons? '(1 2))
#t
procedure
(empty? v) → boolean?
v : any/c
(null? v)와 같아요.
Examples:
> (empty? '(1 2))
#f
> (empty? '())
#t
procedure
(first lst) → any/c
lst : list?
(car lst)와 같지만 리스트(빈 리스트가 아닌)에만 적용돼요.
Example:
> (first '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
1
procedure
(rest lst) → list?
lst : list?
(cdr lst)와 같지만 리스트(빈 리스트가 아닌)에만 적용돼요.
Example:
> (rest '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
'(2 3 4 5 6 7 8 9 10 11 12 13 14 15)
procedure
(second lst) → any/c
lst : list?
리스트의 두 번째 원소를 돌려줘요.
Example:
> (second '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
2
procedure
(third lst) → any/c
lst : list?
리스트의 세 번째 원소를 돌려줘요.
Example:
> (third '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
3
procedure
(fourth lst) → any/c
lst : list?
리스트의 네 번째 원소를 돌려줘요.
Example:
> (fourth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
4
procedure
(fifth lst) → any/c
lst : list?
리스트의 다섯 번째 원소를 돌려줘요.
Example:
> (fifth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
5
procedure
(sixth lst) → any/c
lst : list?
리스트의 여섯 번째 원소를 돌려줘요.
Example:
> (sixth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
6
procedure
(seventh lst) → any/c
lst : list?
리스트의 일곱 번째 원소를 돌려줘요.
Example:
> (seventh '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
7
procedure
(eighth lst) → any/c
lst : list?
리스트의 여덟 번째 원소를 돌려줘요.
Example:
> (eighth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
8
procedure
(ninth lst) → any/c
lst : list?
리스트의 아홉 번째 원소를 돌려줘요.
Example:
> (ninth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
9
procedure
(tenth lst) → any/c
lst : list?
리스트의 열 번째 원소를 돌려줘요.
Example:
> (tenth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
10
procedure
(eleventh lst) → any/c
lst : list?
리스트의 열한 번째 원소를 돌려줘요.
Example:
> (eleventh '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
11
base 패키지의 8.15.0.3 버전에서 추가됐어요.
procedure
(twelfth lst) → any/c
lst : list?
리스트의 열두 번째 원소를 돌려줘요.
Example:
> (twelfth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
12
base 패키지의 8.15.0.3 버전에서 추가됐어요.
procedure
(thirteenth lst) → any/c
lst : list?
리스트의 열세 번째 원소를 돌려줘요.
Example:
> (thirteenth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
13
base 패키지의 8.15.0.3 버전에서 추가됐어요.
procedure
(fourteenth lst) → any/c
lst : list?
리스트의 열네 번째 원소를 돌려줘요.
Example:
> (fourteenth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
14
base 패키지의 8.15.0.3 버전에서 추가됐어요.
procedure
(fifteenth lst) → any/c
lst : list?
리스트의 열다섯 번째 원소를 돌려줘요.
Example:
> (fifteenth '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
15
base 패키지의 8.15.0.3 버전에서 추가됐어요.
procedure
(last lst) → any/c
lst : list?
리스트의 마지막 원소를 돌려줘요.
이 함수는 lst의 길이에 비례하는 시간이 걸려요.
Example:
> (last '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
15
procedure
(last-pair p) → pair?
p : pair?
(아마도 부적절한) 리스트의 마지막 페어를 돌려줘요.
이 함수는 p의 "길이"에 비례하는 시간이 걸려요.
Example:
> (last-pair '(1 2 3 4))
'(4)
procedure
(make-list k v) → list?
k : exact-nonnegative-integer?
v : any/c
길이 k의, 모든 위치에 v를 담은 새로 구성된 리스트를 돌려줘요.
Example:
> (make-list 7 'foo)
'(foo foo foo foo foo foo foo)
procedure
(list-update lst pos updater) → list?
lst : list?
pos : (and/c (>=/c 0) (</c (length lst)))
updater : (-> any/c any/c)
지정한 인덱스에서만 lst와 같은 리스트를 돌려줘요. 지정한 인덱스의 원소는 (updater (list-ref lst pos))예요.
이 함수는 pos에 비례하는 시간이 걸려요.
Example:
> (list-update '(zero one two) 1 symbol->string)
'(zero "one" two)
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(list-set lst pos value) → list?
lst : list?
pos : (and/c (>=/c 0) (</c (length lst)))
value : any/c
지정한 인덱스에서만 lst와 같은 리스트를 돌려줘요. 지정한 인덱스의 원소는 value예요.
이 함수는 pos에 비례하는 시간이 걸려요.
Example:
> (list-set '(zero one two) 2 "two")
'(zero one "two")
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(index-of lst v [is-equal?]) → (or/c exact-nonnegative-integer? #f)
lst : list?
v : any/c
is-equal? : (any/c any/c . -> . any/c) = equal?
member와 같지만 리스트의 꼬리 대신 찾은 첫 원소의 인덱스를 돌려줘요.
Example:
> (index-of '(1 2 3 4) 3)
2
base 패키지의 6.7.0.3 버전에서 추가됐어요.
procedure
(index-where lst proc) → (or/c exact-nonnegative-integer? #f)
lst : list?
proc : (any/c . -> . any/c)
index-of와 같지만 memf의 술어 탐색 동작을 가져요.
Example:
> (index-where '(1 2 3 4) even?)
1
base 패키지의 6.7.0.3 버전에서 추가됐어요.
procedure
(indexes-of lst v [is-equal?])
→ (listof exact-nonnegative-integer?)
lst : list?
v : any/c
is-equal? : (any/c any/c . -> . any/c) = equal?
index-of와 같지만 첫 번째 것뿐 아니라 그 원소가 리스트에서 나타나는 모든 인덱스의 리스트를 돌려줘요.
Example:
> (indexes-of '(1 2 1 2 1) 2)
'(1 3)
base 패키지의 6.7.0.3 버전에서 추가됐어요.
procedure
(indexes-where lst proc) → (listof exact-nonnegative-integer?)
lst : list?
proc : (any/c . -> . any/c)
indexes-of와 같지만 index-where의 술어 탐색 동작을 가져요.
Example:
> (indexes-where '(1 2 3 4) even?)
'(1 3)
base 패키지의 6.7.0.3 버전에서 추가됐어요.
procedure
(take lst pos) → list?
lst : list?
pos : exact-nonnegative-integer?
(take lst pos) → list?
lst : any/c
pos : exact-nonnegative-integer?
원소가 lst의 첫 pos개 원소인 새 리스트를 돌려줘요. lst에 pos개 미만의 원소가 있으면 exn:fail:contract 예외가 발생해요.
lst 인자는 실제로 리스트일 필요 없어요. lst는 단지 적어도 pos개의 페어로 이뤄진 연결 고리로 시작하기만 하면 돼요.
이 함수는 pos에 비례하는 시간이 걸려요.
Examples:
> (take '(1 2 3 4 5) 2)
'(1 2)
> (take 'non-list 0)
'()
procedure
(drop lst pos) → list?
lst : list?
pos : exact-nonnegative-integer?
(drop lst pos) → any/c
lst : any/c
pos : exact-nonnegative-integer?
list-tail과 똑같아요.
procedure
(split-at lst pos) → list? list?
lst : list?
pos : exact-nonnegative-integer?
(split-at lst pos) → list? any/c
lst : any/c
pos : exact-nonnegative-integer?
다음과 같은 결과를 돌려줘요:
(values (take lst pos) (drop lst pos))
다만 더 빠를 수 있어요. 그래도 pos에 비례하는 시간이 걸려요.
procedure
(takef lst pred) → list?
lst : list?
pred : procedure?
(takef lst pred) → list?
lst : any/c
pred : procedure?
pred를 만족하는 한 lst에서 연속적으로 취한 원소들을 담은 새 리스트를 돌려줘요. 돌려주는 리스트는 pred가 #f를 돌려주는 lst의 첫 원소를 포함하지 않고 그 바로 앞까지 포함해요.
lst 인자는 실제로 리스트일 필요 없어요. lst의 페어 사슬은 페어가 아닌 값을 만날 때까지 순회돼요.
Examples:
> (takef '(2 4 5 8) even?)
'(2 4)
> (takef '(2 4 6 8) odd?)
'()
> (takef '(2 4 . 6) even?)
'(2 4)
procedure
(dropf lst pred) → list?
lst : list?
pred : procedure?
(dropf lst pred) → any/c
lst : any/c
pred : procedure?
pred를 만족하는 한 lst의 앞에서 원소를 버려요.
Examples:
> (dropf '(2 4 5 8) even?)
'(5 8)
> (dropf '(2 4 6 8) odd?)
'(2 4 6 8)
procedure
(splitf-at lst pred) → list? list?
lst : list?
pred : procedure?
(splitf-at lst pred) → list? any/c
lst : any/c
pred : procedure?
다음과 같은 결과를 돌려줘요:
(values (takef lst pred) (dropf lst pred))
다만 더 빠를 수 있어요.
procedure
(take-right lst pos) → list?
lst : list?
pos : exact-nonnegative-integer?
(take-right lst pos) → any/c
lst : any/c
pos : exact-nonnegative-integer?
리스트의 길이 pos인 꼬리를 돌려줘요. lst에 pos개 미만의 원소가 있으면 exn:fail:contract 예외가 발생해요.
lst 인자는 실제로 리스트일 필요 없어요. lst는 단지 적어도 pos개의 페어로 이뤄진 연결 고리로 끝나기만 하면 돼요.
이 함수는 lst의 길이에 비례하는 시간이 걸려요.
Examples:
> (take-right '(1 2 3 4 5) 2)
'(4 5)
> (take-right 'non-list 0)
'non-list
procedure
(drop-right lst pos) → list?
lst : list?
pos : exact-nonnegative-integer?
(drop-right lst pos) → list?
lst : any/c
pos : exact-nonnegative-integer?
lst의 접두사를 원소로 하되 길이 pos인 꼬리를 버린 새 리스트를 돌려줘요. lst에 pos개 미만의 원소가 있으면 exn:fail:contract 예외가 발생해요.
lst 인자는 실제로 리스트일 필요 없어요. lst는 단지 적어도 pos개의 페어로 이뤄진 연결 고리로 끝나기만 하면 돼요.
이 함수는 lst의 길이에 비례하는 시간이 걸려요.
Examples:
> (drop-right '(1 2 3 4 5) 2)
'(1 2 3)
> (drop-right 'non-list 0)
'()
procedure
(split-at-right lst pos) → list? list?
lst : list?
pos : exact-nonnegative-integer?
(split-at-right lst pos) → list? any/c
lst : any/c
pos : exact-nonnegative-integer?
다음과 같은 결과를 돌려줘요:
(values (drop-right lst pos) (take-right lst pos))
다만 더 빠를 수 있지만, 그래도 lst의 길이에 비례하는 시간이 걸려요.
Examples:
> (split-at-right '(1 2 3 4 5 . 6) 4)
'(1)
'(2 3 4 5 . 6)
> (split-at-right '(1 2 3 4 5 6) 4)
'(1 2)
'(3 4 5 6)
procedure
(takef-right lst pred) → list?
lst : list?
pred : procedure?
(takef-right lst pred) → any/c
lst : any/c
pred : procedure?
(dropf-right lst pred) → list?
lst : list?
pred : procedure?
(dropf-right lst pred) → list?
lst : any/c
pred : procedure?
(splitf-at-right lst pred) → list? list?
lst : list?
pred : procedure?
(splitf-at-right lst pred) → list? any/c
lst : any/c
pred : procedure?
takef, dropf, splitf-at와 같지만, take-right, drop-right, split-at-right의 오른쪽부터 기능과 결합돼요.
procedure
(list-prefix? l r [same?]) → boolean?
l : list?
r : list?
same? : (any/c any/c . -> . any/c) = equal?
l이 r의 접두사이면 참이에요.
Example:
> (list-prefix? '(1 2) '(1 2 3 4 5))
#t
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(take-common-prefix l r [same?]) → list?
l : list?
r : list?
same? : (any/c any/c . -> . any/c) = equal?
l과 r의 가장 긴 공통 접두사를 돌려줘요.
Example:
> (take-common-prefix '(a b c d) '(a b x y z))
'(a b)
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(drop-common-prefix l r [same?]) → list? list?
l : list?
r : list?
same? : (any/c any/c . -> . any/c) = equal?
공통 접두사를 제거한 l과 r의 꼬리를 돌려줘요.
Example:
> (drop-common-prefix '(a b c d) '(a b x y z))
'(c d)
'(x y z)
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(split-common-prefix l r [same?]) → list? list? list?
l : list?
r : list?
same? : (any/c any/c . -> . any/c) = equal?
가장 긴 공통 접두사와, 공통 접두사를 제거한 l과 r의 꼬리를 함께 돌려줘요.
Example:
> (split-common-prefix '(a b c d) '(a b x y z))
'(a b)
'(c d)
'(x y z)
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(add-between lst v [#:before-first before-first #:before-last before-last
#:after-last after-last #:splice? splice?]) → list?
lst : list?
v : any/c
before-first : list? = '()
before-last : any/c = v
after-last : list? = '()
splice? : any/c = #f
lst와 같은 원소를 담되, lst의 각 원소 쌍 사이에 v를 넣은 리스트를 돌려줘요. 마지막 원소 쌍 사이에는 v 대신 before-last가 들어가요(before-last는 기본값이 v예요).
splice?가 참이면 v와 before-last는 리스트여야 하고, 그 리스트 원소들이 결과에 splice돼요. 또한 splice?가 참일 때 before-first와 after-last가 각각 첫 원소 앞과 마지막 원소 뒤에 삽입돼요.
Examples:
> (add-between '(x y z) '(-) #:before-last '(- -)
#:before-first '(begin) #:after-last '(end LF)
#:splice? #t)
'(begin x - y - - z end LF)
procedure
(append* lst ... lsts) → list?
lst : list?
lsts : (listof list?)
(append* lst ... lsts) → any/c
lst : list?
lsts : list?
append와 같지만 마지막 인자가 append의 인자 리스트로 사용돼요. 그래서 (append* lst ... lsts)는 (apply append lst ... lsts)와 같아요. 즉 append와 append*의 관계는 list와 list* 사이의 관계와 비슷해요.
Examples:
> (cdr (append* (map (lambda (x) (list ", " x))
'("Alpha" "Beta" "Gamma"))))
'("Alpha" ", " "Beta" ", " "Gamma")
procedure
(flatten v) → list?
v : any/c
페어로 이뤄진 임의의 S-표현식 구조를 리스트로 평평하게 만들어요. 더 정확히는 v를 페어가 내부 노드인 이진 트리로 취급하며, 결과 리스트는 트리의 모든 null이 아닌 잎을 중위 순회와 같은 순서로 담아요.
Examples:
> (flatten '((a) b (c (d) . e) ()))
'(a b c d e)
> (flatten 'a)
'(a)
procedure
(check-duplicates lst [same? #:key extract-key #:default failure-result]) → any
lst : list?
same? : (any/c any/c . -> . any/c) = equal?
extract-key : (-> any/c any/c) = (lambda (x) x)
failure-result : failure-result/c = (lambda () #f)
lst의 첫 중복 항목을 돌려줘요. 더 정확히는 (same? (extract-key x) (extract-key y))인 이전 y가 있었던 첫 x를 돌려줘요.
중복을 찾지 못하면 failure-result가 결과를 결정해요:
-
failure-result가 프로시저면 인자 없이 호출되어(꼬리 호출) 결과를 만들어요. -
그렇지 않으면
failure-result가 결과로 돌아와요.
same? 인자는 equal?이나 eqv? 같은 동치 술어여야 해요. equal?, eqv?, eq?, equal-always? 프로시저들은 속도를 위해 자동으로 사전(dictionary)을 사용해요.
Examples:
> (check-duplicates '(1 2 3 4 5 6)
(lambda (x y) (equal? (modulo x 3) (modulo y 3))))
4
> (check-duplicates '(1 2 3 4) #:default "no duplicates")
"no duplicates"
base 패키지의 6.3 버전에서 추가됐어요.
base 패키지의 6.11.0.2 버전에서 #:default 선택 인자를 추가했어요.
procedure
(remove-duplicates lst [same? #:key extract-key]) → list?
lst : list?
same? : (any/c any/c . -> . any/c) = equal?
extract-key : (any/c . -> . any/c) = (lambda (x) x)
lst의 모든 항목을 담되 중복 항목이 없는 리스트를 돌려줘요. 여기서 same?가 리스트의 두 원소가 동등한지 결정해요. 결과 리스트는 lst와 같은 순서이며, 여러 번 나타나는 항목에 대해서는 첫 번째 것이 유지돼요.
#:key 인자 extract-key는 각 리스트 원소에서 키 값을 추출하는 데 사용되며, (same? (extract-key x) (extract-key y))가 참이면 두 항목이 같다고 간주돼요.
check-duplicates처럼 same? 인자가 equal?, eqv?, eq?, equal-always? 중 하나면 성능을 위해 연산을 특수화할 수 있어요.
Examples:
> (remove-duplicates '(a b b a))
'(a b)
> (remove-duplicates '(1 2 1.0 0))
'(1 2 1.0 0)
> (remove-duplicates '(1 2 1.0 0) =)
'(1 2 0)
procedure
(filter-map proc lst ...+) → list?
proc : procedure?
lst : list?
(map proc lst ...)와 같지만, proc이 #false를 돌려주면 그 원소는 결과 리스트에서 생략돼요. 즉 filter-map은 (filter (lambda (x) x) (map proc lst ...))와 동등하지만, 중간 리스트를 만들지 않으므로 더 효율적이에요.
Example:
> (filter-map (lambda (x) (and (negative? x) (abs x))) '(1 2 -3 -4 8))
'(3 4)
procedure
(count proc lst ...+) → exact-nonnegative-integer?
proc : procedure?
lst : list?
(length (filter-map proc lst ...))를 돌려주지만 중간 리스트를 만들지 않아요.
Example:
> (count positive? '(1 -1 2 3 -2 5))
4
procedure
(partition pred lst) → list? list?
pred : procedure?
lst : list?
filter와 비슷하지만 두 값을 돌려줘요: pred가 참 값을 돌려주는 항목들과 pred가 #f를 돌려주는 항목들이에요.
결과는 다음과 같아요:
(values (filter pred lst) (filter (negate pred) lst))
하지만 pred는 lst의 각 항목에 정확히 한 번만 적용돼요.
Example:
> (partition even? '(1 2 3 4 5 6))
'(2 4 6)
'(1 3 5)
procedure
(range end) → list?
end : real?
(range start end [step]) → list?
start : real?
end : real?
step : real? = 1
in-range와 비슷하지만 리스트를 돌려줘요.
결과 리스트는 start에서 시작해, end(제외)에 도달할 때까지 각 연속 원소를 이전 원소에 step을 더해 계산한 숫자들을 담아요. 시작점이 주어지지 않으면 0을 사용해요. step 인자가 주어지지 않으면 1을 사용해요.
in-range처럼, range 적용이 for 절에 직접 나타나면 더 나은 성능을 제공할 수 있어요.
Examples:
> (range 10)
'(0 1 2 3 4 5 6 7 8 9)
> (range 10 20)
'(10 11 12 13 14 15 16 17 18 19)
> (range 20 40 2)
'(20 22 24 26 28 30 32 34 36 38)
> (range 20 10 -1)
'(20 19 18 17 16 15 14 13 12 11)
> (range 10 15 1.5)
'(10 11.5 13.0 14.5)
base 패키지의 6.7.0.4 버전에서 in-range와 같은 방식으로 for와 협력하도록 조정했어요.
procedure
(inclusive-range start end [step]) → list?
start : real?
end : real?
step : real? = 1
in-inclusive-range와 비슷하지만 리스트를 돌려줘요.
결과 리스트는 start에서 시작해, end(포함)에 도달할 때까지 각 연속 원소를 이전 원소에 step을 더해 계산한 숫자들을 담아요. step 인자가 주어지지 않으면 1을 사용해요.
in-inclusive-range처럼, inclusive-range 적용이 for 절에 직접 나타나면 더 나은 성능을 제공할 수 있어요.
Examples:
> (inclusive-range 10 20)
'(10 11 12 13 14 15 16 17 18 19 20)
> (inclusive-range 20 40 2)
'(20 22 24 26 28 30 32 34 36 38 40)
> (inclusive-range 20 10 -1)
'(20 19 18 17 16 15 14 13 12 11 10)
> (inclusive-range 10 15 1.5)
'(10 11.5 13.0 14.5)
base 패키지의 8.0.0.13 버전에서 추가됐어요.
procedure
(append-map proc lst ...+) → list?
proc : procedure?
lst : list?
(append* (map proc lst ...))를 돌려줘요.
Example:
> (append-map vector->list '(#(1) #(2 3) #(4)))
'(1 2 3 4)
procedure
(filter-not pred lst) → list?
pred : (any/c . -> . any/c)
lst : list?
filter와 같지만 pred 술어의 의미가 뒤집혀요: 결과는 pred가 #f를 돌려주는 모든 항목의 리스트예요.
Example:
> (filter-not even? '(1 2 3 4 5 6))
'(1 3 5)
procedure
(shuffle lst) → list?
lst : list?
lst의 모든 원소를 무작위로 섞은 리스트를 돌려줘요.
Examples:
> (shuffle '(1 2 3 4 5 6))
'(1 3 5 4 6 2)
> (shuffle '(1 2 3 4 5 6))
'(6 4 5 1 2 3)
> (shuffle '(1 2 3 4 5 6))
'(2 1 3 6 5 4)
procedure
(combinations lst) → list?
lst : list?
(combinations lst size) → list?
lst : list?
size : exact-nonnegative-integer?
입력 리스트의 원소들의 모든 조합의 리스트(일명 lst의 멱집합)를 돌려줘요. size가 주어지면 결과를 크기 size의 조합으로 제한해요.
Examples:
> (combinations '(1 2 3))
'(() (1) (2) (1 2) (3) (1 3) (2 3) (1 2 3))
> (combinations '(1 2 3) 2)
'((1 2) (1 3) (2 3))
procedure
(in-combinations lst) → sequence?
lst : list?
(in-combinations lst size) → sequence?
lst : list?
size : exact-nonnegative-integer?
입력 리스트의 원소들의 모든 조합의 시퀀스를 돌려줘요. size가 주어지면 길이 size의 모든 조합을 돌려줘요. 조합을 한 번에 모두 만들지 않고 하나씩 만들어요.
Examples:
> (time (begin (combinations (range 15)) (void)))
cpu time: 25 real time: 6 gc time: 0
> (time (begin (in-combinations (range 15)) (void)))
cpu time: 0 real time: 0 gc time: 0
procedure
(permutations lst) → list?
lst : list?
입력 리스트의 모든 순열의 리스트를 돌려줘요. 이 함수는 원소를 검사하지 않고 동작하므로 반복된 원소를 무시해요(그 결과 반복된 순열이 생겨요). 입력 리스트가 256개보다 많은 원소를 포함하면 오류를 발생시켜요.
Examples:
> (permutations '(1 2 3))
'((1 2 3) (2 1 3) (1 3 2) (3 1 2) (2 3 1) (3 2 1))
> (permutations '(x x))
'((x x) (x x))
procedure
(in-permutations lst) → sequence?
lst : list?
입력 리스트의 모든 순열의 시퀀스를 돌려줘요. (in-list (permutations l))과 동등하지만 각 반복에서 순열을 하나씩 만들므로 훨씬 빠르죠. 입력 리스트가 256개보다 많은 원소를 포함하면 오류를 발생시켜요.
procedure
(argmin proc lst) → any/c
proc : (-> any/c real?)
lst : (and/c pair? list?)
proc의 결과를 최소화하는 리스트 lst의 첫 원소를 돌려줘요. 빈 리스트에서는 오류를 신호로 보내요. min도 참고하세요.
Examples:
> (argmin car '((3 pears) (1 banana) (2 apples)))
'(1 banana)
> (argmin car '((1 banana) (1 orange)))
'(1 banana)
procedure
(argmax proc lst) → any/c
proc : (-> any/c real?)
lst : (and/c pair? list?)
proc의 결과를 최대화하는 리스트 lst의 첫 원소를 돌려줘요. 빈 리스트에서는 오류를 신호로 보내요. max도 참고하세요.
Examples:
> (argmax car '((3 pears) (1 banana) (2 apples)))
'(3 pears)
> (argmax car '((3 pears) (3 oranges)))
'(3 pears)
procedure
(group-by key lst [same?]) → (listof list?)
key : (-> any/c any/c)
lst : list?
same? : (any/c any/c . -> . any/c) = equal?
주어진 리스트를 동치 클래스로 그룹화해요. 동치는 same?에 의해 결정돼요. 각 동치 클래스 안에서 group-by는 원래 리스트의 순서를 보존해요. 동치 클래스 자체는 입력에서 처음 등장한 순서로 정렬돼요.
Example:
> (group-by (lambda (x) (modulo x 3)) '(1 2 1 2 54 2 5 43 7 2 643 1 2 0))
'((1 1 43 7 643 1) (2 2 2 5 2 2) (54 0))
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(cartesian-product lst ...) → (listof list?)
lst : list?
주어진 리스트들의 n-항 카테시안 곱을 계산해요.
Examples:
> (cartesian-product '(1 2 3) '(a b c))
'((1 a) (1 b) (1 c) (2 a) (2 b) (2 c) (3 a) (3 b) (3 c))
> (cartesian-product '(4 5 6) '(d e f) '(#t #f))
'((4 d #t)
(4 d #f)
(4 e #t)
(4 e #f)
(4 f #t)
(4 f #f)
(5 d #t)
(5 d #f)
(5 e #t)
(5 e #f)
(5 f #t)
(5 f #f)
(6 d #t)
(6 d #f)
(6 e #t)
(6 e #f)
(6 f #t)
(6 f #f))
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(remf pred lst) → list?
pred : procedure?
lst : list?
pred가 참 값을 돌려주는 lst의 첫 원소를 생략한, lst와 같은 리스트를 돌려줘요.
Example:
> (remf negative? '(1 -2 3 4 -5))
'(1 3 4 -5)
base 패키지의 6.3 버전에서 추가됐어요.
procedure
(remf* pred lst) → list?
pred : procedure?
lst : list?
remf와 같지만 pred가 참 값을 돌려주는 모든 원소를 제거해요.
Example:
> (remf* negative? '(1 -2 3 4 -5))
'(1 3 4)
base 패키지의 6.3 버전에서 추가됐어요.
4.10.9 더 많은 리스트 그룹화 (More List Grouping)
(require racket/list/grouping)
package: sequence-tools-lib
이 절에서 다루는 바인딩들은 racket/base나 racket이 아니라 racket/list/grouping 라이브러리에서 제공돼요.
이 절의 바인딩들은 기본 시퀀스 라이브러리의 확장 역할을 하는 sequence-tools-lib 패키지에서 제공돼요.
procedure
(windows size step lst) → (listof list?)
size : exact-positive-integer?
step : exact-positive-integer?
lst : list?
각 창이 size개의 원소를 담고, 창이 각 반복에서 step 위치만큼 슬라이딩하는 슬라이딩 창들의 리스트를 돌려줘요. 남은 원소의 수가 size보다 작으면 그 원소들은 버려져요.
Examples:
> (windows 3 1 '(1 2 3 4))
'((1 2 3) (2 3 4))
> (windows 2 3 '(1 2 3))
'((1 2))
> (windows 1 2 '(1 2 3 4))
'((1) (3))
procedure
(slice-by proc lst) → (listof list?)
proc : (-> any/c any/c any/c)
lst : list?
각 인접한 원소 쌍을 비교해 구성된 하위 리스트(조각)를 각 원소로 담는 리스트를 돌려줘요. proc을 만족하는 모든 원소 쌍은 하나의 조각으로 함께 그룹화되고, 그렇지 않으면 그 원소가 새 조각을 시작해요.
Examples:
> (slice-by eq? '(1 1 2 1 3 3))
'((1 1) (2) (1) (3 3))
> (slice-by < '(1 2 3 3 4))
'((1 2 3) (3 4))
4.10.10 불변 순환 데이터 (Immutable Cyclic Data)
procedure
(make-reader-graph v) → any/c
v : any/c
v와 같은 값을 돌려주되, make-placeholder로 만든 플레이스홀더는 그들이 담는 값으로, make-hash-placeholder로 만든 해시 플레이스홀더는 불변 해시 테이블로 대체해요. v의 어떤 부분도 변형되지 않아요. 대신 결과 그래프를 구성하기 위해 v의 일부가 필요에 따라 복사되는데, 주어진 값에 대해 기껏해야 하나의 복사본이 만들어져요.
복사된 값들이 불변일 수 있고 복사본도 불변이므로, make-reader-graph는 불변 페어·벡터·박스·해시 테이블만 포함하는 순환을 만들 수 있어요.
다음 종류의 값만 플레이스홀더 검출을 위해 복사되고 순회돼요:
- 페어
- 가변·불변 벡터
- 가변·불변 박스
- 가변·불변 해시 테이블
- prefab 구조체 타입의 인스턴스
make-placeholder와make-hash-placeholder로 만든 플레이스홀더
이런 제약 때문에 make-reader-graph는 read가 만드는 것과 정확히 같은 종류의 순환 값을 만들어요.
Example:
> (let* ([ph (make-placeholder #f)]
[x (cons 1 ph)])
(placeholder-set! ph x)
(make-reader-graph x))
#0='(1 . #0#)
procedure
(placeholder? v) → boolean?
v : any/c
v가 make-placeholder로 만든 플레이스홀더면 #t를, 그렇지 않으면 #f를 돌려줘요.
procedure
(make-placeholder v) → placeholder?
v : any/c
placeholder-set!과 make-reader-graph와 함께 사용할 플레이스홀더를 돌려줘요. v 인자는 플레이스홀더의 초기 값을 제공해요.
procedure
(placeholder-set! ph datum) → void?
ph : placeholder?
datum : any/c
ph의 값을 v로 바꿔요.
procedure
(placeholder-get ph) → any/c
ph : placeholder?
ph의 값을 돌려줘요.
procedure
(hash-placeholder? v) → boolean?
v : any/c
v가 make-hash-placeholder로 만든 해시 플레이스홀더면 #t를, 그렇지 않으면 #f를 돌려줘요.
procedure
(make-hash-placeholder assocs) → hash-placeholder?
assocs : (listof pair?)
make-immutable-hash와 같지만 make-reader-graph와 함께 사용할 해시 플레이스홀더를 만들어요.
procedure
(make-hasheq-placeholder assocs) → hash-placeholder?
assocs : (listof pair?)
make-immutable-hasheq와 같지만 make-reader-graph와 함께 사용할 해시 플레이스홀더를 만들어요.
procedure
(make-hasheqv-placeholder assocs) → hash-placeholder?
assocs : (listof pair?)
make-immutable-hasheqv와 같지만 make-reader-graph와 함께 사용할 해시 플레이스홀더를 만들어요.
procedure
(make-hashalw-placeholder assocs) → hash-placeholder?
assocs : (listof pair?)
make-immutable-hashalw와 같지만 make-reader-graph와 함께 사용할 해시 플레이스홀더를 만들어요.
base 패키지의 8.5.0.3 버전에서 추가됐어요.
더 알아보기
- Mutable Pairs and Lists — 가변 페어와 리스트.
- Sequences — 시퀀스.
- Racket Guide: Pairs and Lists — 페어와 리스트 소개.