라이브러리와 컬렉션
라이브러리와 컬렉션 (Libraries and Collections)
Racket에서 라이브러리(library)는 여러 프로그램이 쓰도록 만든 모듈 선언이에요. Racket은 라이브러리들을 다시 컬렉션(collection)으로 묶어요. 이 문서는 컬렉션이 어떻게 구성되고, 모듈 이름이 어떻게 컬렉션 안의 파일로 해석되는지 설명할게요.
출처: Racket Reference
본문
18.2 라이브러리와 컬렉션
라이브러리는 여러 프로그램이 쓰기 위한 모듈 선언이에요. Racket은 라이브러리들을 컬렉션으로 다시 묶어요. 보통 컬렉션은 패키지(package)를 통해 추가되고(Racket의 Package Management 참고), 패키지 관리자는 Racket 코어 밖에서 동작하지만 컬렉션 링크 파일(collection links file)을 통해 코어 런타임 시스템을 설정해요.
컬렉션 안의 라이브러리는 lib 경로(require 참고)나 기호 축약형으로 참조돼요. 예를 들어 다음 모듈은 "setup" 컬렉션에서 "getinfo.rkt" 라이브러리 모듈을, "games" 컬렉션의 "cards" 하위 컬렉션에서 "cards.rkt" 라이브러리 모듈을 사용해요:
#lang racket
(require (lib "setup/getinfo.rkt")
(lib "games/cards/cards.rkt"))
....
이 예시는 기호 축약형으로 더 간결하고 흔하게 쓸 수 있어요:
#lang racket
(require setup/getinfo
games/cards/cards)
....
require 폼에서 식별자 id가 쓰이면 (lib rel-string)으로 변환되는데, 여기서 rel-string은 id의 문자열 형태예요.
(lib rel-string)의 rel-string은 컬렉션을 이름 짓는 하나 이상의 경로 요소와, 그다음 라이브러리 파일을 이름 짓는 마지막 경로 요소로 구성돼요. 경로 요소들은 /로 구분돼요. rel-string에 /가 없으면 경로에 /main.rkt이 암묵적으로 붙어요. rel-string에 /가 있지만 파일 접미사로 끝나지 않으면 경로에 .rkt이 암묵적으로 붙어요.
라이브러리는 PLaneT 패키지로도 배포될 수 있어요. 그런 라이브러리들은 planet 모듈 경로(require 참고)로 참조되고, 컬렉션을 통해서가 아니라 Racket이 필요할 때 다운로드해요.
planet 또는 lib 경로를 모듈 선언으로 변환하는 것은 current-module-name-resolver 매개변수가 지정하는 모듈 이름 리졸버(resolver)가 결정해요.
18.2.1 컬렉션 검색 설정
기본 모듈 이름 리졸버의 경우, 컬렉션 검색 경로는 current-library-collection-links 매개변수와 current-library-collection-paths 매개변수로 결정돼요:
- 가장 기초적인 컬렉션 기반 모듈들은 Racket 실행 파일 기준의
"collects"디렉터리에 위치해요. 컬렉션의 라이브러리들은 컬렉션 이름과 일치하는 이름의 디렉터리 안에 묶여 있어요."collects"디렉터리로 가는 경로는 보통current-library-collection-paths에 포함돼요. - 컬렉션 기반 라이브러리들은
"collects"디렉터리처럼 구조화된 다른 디렉터리(어쩌면 사용자 전용)에도 설치될 수 있어요. 그 추가 디렉터리들은current-library-collection-paths매개변수에 동적으로(racket에 대한 명령줄 인자로) 또는PLTCOLLECTS환경 변수를 설정해서 포함할 수 있어요.find-library-collection-paths참고. - 컬렉션 링크 파일은 최상위 컬렉션 이름에서 디렉터리로의 매핑과, 추가 "collects"류 디렉터리(컬렉션 이름과 일치하는 이름의 하위 디렉터리를 가진)를 제공해요. 검색할 각 컬렉션 링크 파일은
current-library-collection-links매개변수가 참조해요. 이 매개변수는 파일의 내용이 아니라 파일을 참조하므로, 파일의 변경을 감지해 나중의 모듈 해석에 영향을 줄 수 있어요.find-library-collection-links도 함께 보세요. current-library-collection-links매개변수의 값은 컬렉션 링크 파일과 같은 내용을 제공하는 해시 테이블도 포함할 수 있어요: 기호 형태의 컬렉션 이름에서 컬렉션의 경로 리스트로의 매핑, 또는#f에서 "collects"류 경로 리스트로의 매핑이에요.- 마지막으로
current-library-collection-links매개변수의 값은#f를 포함하는데, 모듈 이름 리졸버가current-library-collection-links안의 파일과 해시 테이블에 상대적으로current-library-collection-paths를 검사해야 하는 검색 과정의 지점을 나타내요.
모듈 참조 rel-string을 해석하려면, 기본 모듈 이름 리졸버가 current-library-collection-links의 컬렉션 링크를 처음부터 끝까지 검색해 rel-string을 담은 첫 디렉터리를 찾아요. current-library-collection-links 안에 #f가 있는 곳에서 current-library-collection-paths를 통한 검색을 끼워 넣어요. 링크 테이블과 검색 경로의 각 요소에 대한 파일 시스템 트리는, 같은 컬렉션에 해당하는 다른 경로 요소들의 파일 시스템 트리와 사실상 이어 붙여져요. 일부 Racket 도구는 모듈 경로 이름의 유일한 해석에 의존하므로, 설치와 구성이 같은 컬렉션·파일 조합에 여러 파일이 일치하게 해서는 안 돼요.
current-library-collection-links 매개변수의 값은 racket 실행 파일이 (find-library-collection-links)의 결과로 초기화하고, current-library-collection-paths 매개변수의 값은 (find-library-collection-paths)의 결과로 초기화해요.
18.2.2 컬렉션 링크 (Collection Links)
컬렉션 링크 파일은 collection-file-path, collection-path, 그리고 기본 모듈 이름 리졸버가 (current-library-collection-paths) 검색 경로를 시도하기 전에 컬렉션을 찾는 데 사용돼요. 사용할 컬렉션 링크 파일은 current-library-collection-links 매개변수가 결정하는데, 이 매개변수는 find-library-collection-links의 결과로 초기화돼요.
컬렉션 링크 파일은 기본 리더 매개변수 설정으로 읽어 리스트를 얻어요. 리스트의 각 요소는 다음 형태 중 하나의 링크 명세여야 해요: (list string encoded-path), (list string encoded-path regexp), (list 'root encoded-path), (list 'root encoded-path regexp), (list 'static-root encoded-path), (list 'static-root encoded-path regexp).
문자열은 최상위 컬렉션을 이름 짓는데, 그 경우 encoded-path는 컬렉션의 경로로 쓸 수 있는 경로를 나타내요(string이 이름을 짓는 encoded-path의 하위 디렉터리가 아니라 직접). 반면 'root 항목은 (current-library-collection-paths)의 경로처럼 동작해요. 'static-root 항목은 'root 항목과 같지만, 컬렉션 링크 파일이 바뀌지 않는 한 디렉터리의 즉각적인 내용이 변하지 않는다고 가정해요.
각 encoded-path는 문자열이거나, bytes->path로 경로로 변환되는 바이트 문자열이거나, bytes->path-element로 변환되는 바이트 문자열과 'up, 'same 표시의 상대 경로 요소 리스트(build-path로 결합)예요.
encoded-path가 상대 경로를 나타내면, 그것은 컬렉션 링크 파일을 포함한 디렉터리를 기준으로 해요. 링크에 regexp가 지정되면, (regexp-match? regexp (version))이 참 결과를 만들 때만 그 링크가 사용돼요.
단일 최상위 컬렉션은 컬렉션 링크 파일에 여러 링크를 가질 수 있고, 'root 항목은 얼마든지 나타날 수 있어요. 대응하는 경로들은 파일이나 하위 컬렉션을 찾기 위해 순서대로 시도되므로 사실상 이어 붙여져요.
raco link 명령줄 도구는 컬렉션 링크 파일에서 링크를 표시·설치·제거할 수 있어요. 자세한 내용은 raco: Racket Command-Line Tools의 "raco link: Library Collection Links"를 참고하세요.
Changed in version 8.1.0.6 of package base: Changed encoded-path to allow bytes strings and lists.
18.2.3 컬렉션 경로와 매개변수
(find-library-collection-paths [pre-extras post-extras config name])
→ (listof path?)
pre-extras : (listof path-string?) = null
post-extras : (listof path-string?) = null
config : hash? = (read-installation-configuration-table)
name : (get-installation-name config)
보통 current-library-collection-paths를 초기화하는 데 쓰는 경로 리스트를 다음과 같이 만들어요:
(build-path (find-system-path 'addon-dir) name "collects")가 만든 경로는,use-user-specific-search-paths매개변수의 값이#f가 아니면, 기본 컬렉션 경로 리스트의 첫 요소예요.pre-extras에 제공된 추가 디렉터리들은 실행 파일 기준의 완전한 경로로 변환되어 기본 컬렉션 경로 리스트의 다음에 포함돼요.(find-system-path 'collects-dir)이 지정하는 디렉터리가 절대적이거나, (실행 파일 기준으로) 상대적이고 존재하면, 기본 컬렉션 경로 리스트의 끝에 추가돼요.post-extras에 제공된 추가 디렉터리들은 실행 파일 기준의 완전한 경로로 변환되어 기본 컬렉션 경로 리스트의 마지막에 포함돼요.config가'collects-search-dirs에 대한 값이 있으면, 앞의 세 항목이 만든 기본 컬렉션 경로 리스트 대신 그것이 쓰여요. 그리고'collects-search-dirs리스트 안의 어떤#f위치에도 기본값이 이어 붙여져요.config에'collects-search-dirs값이 없으면 기본 컬렉션 경로 리스트가 쓰여요.PLTCOLLECTS환경 변수가 정의되어 있으면,use-user-specific-search-paths의 값이 참인 한,path-list-string->path-list로 기본 리스트와 결합돼요. 정의되지 않았거나use-user-specific-search-paths의 값이#f이면 앞의 네 항목이 만든 컬렉션 경로 리스트가 직접 쓰여요.
참고로 Unix와 Mac OS에서는 경로를 :로, Windows에서는 ;로 구분해요. 또한 path-list-string->path-list는 빈 경로 위치에 기본 경로를 이어 붙여요. 예를 들어 많은 Unix 셸에서 PLTCOLLECTS를 ":'pwd'", "'pwd':", "'pwd'"로 설정해 현재 디렉터리를 각각 기본 경로 뒤, 앞, 대신 검색하도록 지정할 수 있어요.
Changed in version 8.4.0.3 of package base: Added the config and name arguments.
(find-library-collection-links [config] name)
→ (listof (or/c #f (and/c path? complete-path?)))
config : hash? = (read-installation-configuration-table)
name : (get-installation-name config)
보통 current-library-collection-links를 초기화하는 데 쓰는 경로와 #f의 리스트를 다음과 같이 만들어요:
- 리스트는
#f에서 시작하는데, 기본 모듈 이름 리졸버,collection-file-path,collection-path가 컬렉션 링크 파일 전에current-library-collection-paths의 경로를 시도하게 해요. use-user-specific-search-paths와use-collection-link-paths의 값이 참인 동안, 결과 리스트의 두 번째 요소는 사용자 전용 컬렉션 링크 파일의 경로인데, 기본적으로(build-path (find-system-path 'addon-dir) name "links.rktd")이지만,config의'links-file값으로 대체될 수 있어요.use-collection-link-paths의 값이 참인 동안, 리스트의 나머지는get-links-search-files의 결과와 같은 결과를 포함하는데, 설치의"config.rktd"파일을 읽는 대신 제공되면config를 사용해요. 보통 그 결과는 단일 경로(build-path (find-config-dir) "links.rktd")를 가진 리스트예요.
Changed in version 8.4.0.3 of package base: Added the config and name arguments.
(collection-file-path file collection ...+ [#:check-compiled? check-compiled?])
→ path?
file : path-string?
collection : path-string?
check-compiled? : any/c = (regexp-match? #rx"[.]rkt$" file)
(collection-file-path file collection ...+ #:fail fail-proc
[#:check-compiled? check-compiled?]) → any
file : path-string?
collection : path-string?
fail-proc : (string? . -> . any)
check-compiled? : any/c = (regexp-match? #rx"[.]rkt$" file)
collection들이 지정한 컬렉션의 file이 가리키는 파일의 경로를 반환해요. 두 번째 collection(있으면)은 하위 컬렉션을 이름 짓고, 그다음도 마찬가지예요. 검색은 current-library-collection-links와 current-library-collection-paths의 값을 사용해요.
setup/collection-search의 collection-search도 함께 보세요.
file을 찾지 못했지만 file이 ".rkt"로 끝나고 ".ss" 접미사의 파일이 존재하면, ".ss" 파일의 디렉터리가 사용돼요. file을 찾지 못했고 ".rkt"/".ss" 변환이 적용되지 않지만 collection들에 해당하는 디렉터리가 발견되면, 그런 첫 디렉터리를 쓰는 경로가 반환돼요.
check-compiled?가 참이면 검색은 use-compiled-file-paths와 current-compiled-file-roots에도 의존해요. file을 찾지 못하면 ".zo" 접미사의 컴파일된 형태의 file이 기본 컴파일드 로드 핸들러와 같은 방식으로 검사돼요. 컴파일된 파일을 찾으면 collection-file-path의 결과는 찾은 컴파일된 파일에 대해 그 파일 자체가 (존재한다면) 차지했을 위치를 보고해요.
마지막으로 컬렉션을 찾지 못했고 fail-proc가 제공되면, fail-proc가 오류 메시지("collection-file-path:"로 시작하거나 출처를 주장하지 않는)에 적용되고, 그 결과가 collection-file-path의 결과예요. fail-proc가 제공되지 않고 컬렉션을 찾지 못하면 exn:fail:filesystem 예외가 발생해요.
> (collection-file-path "main.rkt" "racket" "base")
#<path:path/to/collects/racket/base/main.rkt>
> (collection-file-path "sandwich.rkt" "bologna")
collection-file-path: collection not found
collection: "bologna"
in collection directories:
/home/scheme/pltbuild/racket/racket/collects/
... [261 additional linked and package directories]
Changed in version 6.0.1.12 of package base: Added the check-compiled? argument.
(collection-path collection ...+) → path?
collection : path-string?
(collection-path collection ...+ #:fail fail-proc) → any
collection : path-string?
fail-proc : (string? . -> . any)
참고: 이 함수는 폐기(deprecated)됐어요. collection-file-path를 쓰세요. 컬렉션 이어붙이기(splicing)는 주어진 컬렉션이 여러 경로를 가질 수 있음을 뜻해요. 예를 들어 여러 패키지가 한 컬렉션에 모듈을 제공할 때요.
collection-file-path와 같지만 파일 이름을 지정하지 않아, collection들이 가리키는 디렉터리를 반환해요. 여러 디렉터리가 컬렉션에 해당하면 검색 순서(Collection Search Configuration 참고)에서 처음 발견된 것이 반환돼요.
(current-library-collection-paths)
→ (listof (and/c path? complete-path?))
(current-library-collection-paths paths) → void?
paths : (listof (and/c path-string? complete-path?))
기본 모듈 이름 리졸버를 통해 (예를 들어 require에서 참조되는) 라이브러리를 찾고, collection-path와 collection-file-path를 통해 경로를 찾는 완전한 디렉터리 경로 리스트를 결정하는 매개변수예요. 자세한 내용은 Collection Search Configuration 참고.
(current-library-collection-links)
→ (listof (or/c #f
(and/c path? complete-path?)
(hash/c (or/c (and/c symbol? module-path?) #f)
(listof (and/c path? complete-path?)))))
(current-library-collection-links paths) → void?
paths : (listof (or/c #f
(and/c path-string? complete-path?)
(hash/c (or/c (and/c symbol? module-path?) #f)
(listof (and/c path-string? complete-path?)))))
기본 모듈 이름 리졸버를 통해 (예를 들어 require에서 참조되는) 라이브러리를 찾고, collection-path와 collection-file-path를 통해 경로를 찾는 컬렉션 링크 파일, 추가 경로, current-library-collection-paths의 상대적 검색 순서를 결정하는 매개변수예요. 자세한 내용은 Collection Search Configuration 참고.
(use-user-specific-search-paths) → boolean?
(use-user-specific-search-paths on?) → void?
on? : any/c
(find-system-path 'addon-dir)이 만든 디렉터리에 있는 사용자 전용 경로가 컬렉션 및 다른 파일의 검색 경로에 포함되는지 결정하는 매개변수예요. 예를 들어 이 매개변수의 값이 #f이면 find-library-collection-paths의 초기값이 사용자 전용 컬렉션 디렉터리를 생략해요. racket에 -U 또는 --no-user-path 인자를 주면 use-user-specific-search-paths가 #f로 초기화돼요.
(use-collection-link-paths) → boolean?
(use-collection-link-paths on?) → void?
on? : any/c
컬렉션 링크 파일이 find-library-collection-links의 결과에 포함되는지 결정하는 매개변수예요. 이 매개변수의 값이 시작 시 #f이면 컬렉션 링크 파일은 Racket 프로세스에 영구적으로 사실상 비활성화돼요. 특히 racket에 -X 또는 --collects 인자로 빈 문자열을 주면, current-library-collection-paths가 빈 리스트로 초기화될 뿐만 아니라 use-collection-link-paths도 #f로 초기화돼요.
(read-installation-configuration-table)
→ (and/c hash? immutable?)
설치의 "config.rktd" 파일(Installation Configuration and Search Paths 참고)의 내용을, 그 내용이 해시 테이블인 한 반환하고, 그렇지 않으면 빈 해시 테이블을 반환해요. Added in version 8.4.0.3 of package base.