임퍼서네이터와 셔프런

임퍼서네이터와 셔프런 (Impersonators and Chaperones)

임퍼서네이터(impersonator)는 값의 래퍼로, 래퍼가 값의 일부 연산을 가로채(redirect) 다시 보내는 구조예요. 계약 시스템이 고차 값에 계약을 부착하는 핵심 메커니즘으로, 셔프런(chaperone)은 그중 값의 세밀화를 제한한 특별한 종류예요.

출처: Racket Reference

본문

14.5 임퍼서네이터와 셔프런

임퍼서네이터는 값의 래퍼로서, 래퍼가 값의 일부 연산을 가로채 다시 보내요. 임퍼서네이터는 프로시저, 접근자(accessor)나 뮤테이터(mutator)를 쓸 수 있는 구조체, 구조체 타입, 해시 테이블, 벡터, 박스, 채널, 프롬프트 태그에만 적용돼요.

임퍼서네이터는 원래 값과 equal?이지만, eq?는 아니에요.

셔프런은 임퍼서네이터의 한 종류인데, 값의 연산을 세밀화(refine)하는 것이 부수 효과(특히 예외 발생)나 그 연산에 공급되거나 산출된 값의 셔프런을 만드는 것으로 제한돼요. 예를 들어 벡터 셔프런은 접근된 벡터 슬롯이 문자열을 담고 있으면 vector-ref가 예외를 발생시키도록 가로챌 수 있고, vector-ref의 결과가 접근된 벡터 슬롯에 있는 값의 셔프런 변형이 되게 할 수도 있어요. 하지만 vector-ref가 벡터 슬롯의 값과 임의로 다른 값을 만들도록 가로챌 수는 없어요.

반면 셔프런이 아닌 임퍼서네이터는 한 값을 다른 값으로 아무렇게나 바꾸도록 연산을 세밀화할 수 있어요. 임퍼서네이터는 불변 값에 적용되거나 구조체 타입 인스턴스의 불변 필드 접근을 세밀화할 수 없는데, 연산의 임의 가로채기가 본질적으로 임퍼서네이트된 값의 변형(mutation)이기 때문이에요.

다음 연산들 각각은, 그 연산이 임퍼서네이터 작성자에게 이용 가능하다는 가정 아래, 임퍼서네이터를 통해 인자의 연산을 임의 프로시저로 가로챌 수 있음을 주의하세요:

  • 구조체 필드 접근자
  • 구조체 필드 뮤테이터
  • 구조체 타입 속성 접근자
  • 프로시저 애플리케이션
  • unbox
  • set-box!
  • vector-ref
  • vector-set!
  • hash-ref
  • hash-set
  • hash-set!
  • hash-remove
  • hash-remove!
  • channel-get
  • channel-put
  • call-with-continuation-prompt
  • abort-current-continuation

값을 출력하는 것 같은 파생 연산들은 접근자 함수를 쓰기 때문에 임퍼서네이터를 통해 가로챌 수 있어요. 반면 equal?, equal-hash-code, equal-secondary-hash-code 연산은 임퍼서네이터를 우회할 수 있어요(그러나 꼭 그래야 하는 건 아니에요).

값에 대해 작동하는 연산을 가로채는 것에 더해, 임퍼서네이터는 임퍼서네이트된 값에 대한 임퍼서네이터 속성(impersonator property)을 포함할 수 있어요. 임퍼서네이터 속성은 구조체 타입 속성과 비슷하지만, 구조체 타입과 그 인스턴스 대신 임퍼서네이터에 적용돼요.

(impersonator? v) → boolean?
  v : any/c

vimpersonate-procedureimpersonate-struct 같은 프로시저가 만든 임퍼서네이터이면 #t, 그렇지 않으면 #f를 반환해요. 프로그램과 라이브러리는 일반적으로 impersonator?를 피하고, 임퍼서네이터를 임퍼서네이터가 아닌 값과 동일하게 취급해야 해요. 드물게는 연산을 임의 프로시저로 가로채는 임퍼서네이터를 막기 위해 impersonator?가 필요할 수 있어요.

impersonator?의 한계는 prop:impersonator-of 속성으로 구조체 타입을 인스턴스화해 만든 임퍼서네이터를 인식하지 못한다는 거예요. 이 한계는 그런 임퍼서네이터들이 구조체 접근·변형 연산을 임의 프로시저로 가로챌 수 없다는 사실을 반영해요.

(chaperone? v) → boolean?
  v : any/c

v가 셔프런이면 #t, 그렇지 않으면 #f를 반환해요. 프로그램과 라이브러리는 impersonator?를 피해야 하는 것과 같은 이유로 일반적으로 chaperone?를 피해야 해요. chaperone?의 참 값은 impersonator?의 참 값을 함의해요.

(impersonator-of? v1 v2) → boolean?
  v1 : any/c
  v2 : any/c

v1이 임퍼서네이터를 무시하고 모듈로 v2와 동등하다고 간주될 수 있는지 나타내요.

서로 eq?인 두 값은 모두 impersonator-of?예요. 임퍼서네이터를 포함하지 않는 값들에 대해 v1v2equal?이면 서로의 임퍼서네이터로 간주돼요.

v1 또는 v2 중 적어도 하나가 임퍼서네이터이면:

  • v1v1*을 임퍼서네이트한다면, (impersonator-of? v1 v2)(impersonator-of? v1* v2)#t일 때만 #t예요.
  • v2v2*을 임퍼서네이트하는 비간섭(non-interposing) 임퍼서네이터, 즉 그 간섭 프로시저가 전부 #f인 경우, (impersonator-of? v1 v2)(impersonator-of? v1 v2*)#t일 때만 #t예요.
  • v2가 적어도 하나의 #f가 아닌 간섭 프로시저로 만들어진 임퍼서네이터인데 v1이 임퍼서네이터가 아니면, (impersonator-of? v1 v2)#f예요.

그 외에 v1v2 중 어느 것도 임퍼서네이터가 아니지만 둘 중 하나가 부분으로 임퍼서네이터를 포함하면(예: v1이 원소 중 하나로 임퍼서네이터를 가진 리스트), (impersonator-of? v1 v2)v1v2를 (equal?처럼) 재귀적으로 비교해, 모든 부분이 impersonator-of?이면 #t를 반환해요.

> (impersonator-of? (impersonate-procedure add1 (λ (x) x))
                    add1)
#t
> (impersonator-of? (impersonate-procedure add1 (λ (x) x))
                    sub1)
#f
> (impersonator-of? (impersonate-procedure
                      (impersonate-procedure add1 (λ (x) x)) (λ (x) x))
                    add1)
#t
> (impersonator-of? (impersonate-procedure add1 (λ (x) x))
                    (impersonate-procedure add1 #f))
#t
> (impersonator-of? (impersonate-procedure add1 (λ (x) x))
                    (impersonate-procedure add1 (λ (x) x)))
#f
> (impersonator-of? (list 1 2)
                    (list 1 2))
#t
> (impersonator-of? (list (impersonate-procedure add1 (λ (x) x)) sub1)
                    (list add1 sub1))
#t
(chaperone-of? v1 v2) → boolean?
  v1 : any/c
  v2 : any/c

v1이 셔프런을 무시하고 모듈로 v2와 동등하다고 간주될 수 있는지 나타내요.

셔프런이나 다른 임퍼서네이터를 포함하지 않는 값들에 대해, v1v2equal-always?이면 서로의 셔프런으로 간주될 수 있어요. equal-always?equal?이되 v1v2 안의 대응하는 가변 벡터·박스·해시 테이블·문자열·바이트 문자열·가변 쌍·가변 구조체가 eq?여야 함을 요구해요.

그 외에는 v2 안의 셔프런과 다른 임퍼서네이터들이 impersonator-of?가 임퍼서네이터 보존을 요구하는 방식과 유사하게 v1 안에서 온전히 보존되어야 해요. 게다가 v1에는 v2의 대응 값이 같은 임퍼서네이터가 아닌 비셔프런 임퍼서네이터가 없어야 해요.

셔프런-of?는 impersonator-of?를 함의하지만 그 역은 성립하지 않음을 주의하세요.

(impersonator-ephemeron v) → ephemeron?
  v : any/c

v의 도달 가능성(가비지 컬렉션의 의미에서. Garbage Collection 참고)을, v가 임퍼서네이터인 어떤 값의 도달 가능성과 연결하는 데 쓸 ephemeron을 만들어요. 즉 v는 결과 ephemeron이 도달 가능하고 v가 임퍼서네이트하는 어떤 값(자기 자신 포함)도 도달 가능한 동안 도달 가능한 것으로 간주돼요. ephemeron의 용어로 v는 ephemeron의 값이고, v가 임퍼서네이트하는 모든 값은 키예요.

(procedure-impersonator*? v) → boolean?
  v : any/c

vimpersonate-procedure*chaperone-procedure*로 만들어진 프로시저 임퍼서네이터이거나, impersonate-procedure*chaperone-procedure*로 만들어진 값의 임퍼서네이터·셔프런(아마 전이적으로)이면 #t를 반환해요.

14.5.1 임퍼서네이터 생성자 (Impersonator Constructors)

(impersonate-procedure proc wrapper-proc prop prop-val ... ...)
 → (and/c procedure? impersonator?)
  proc : procedure?
  wrapper-proc : (or/c procedure? #f)
  prop : impersonator-property?
  prop-val : any/c

proc와 같은 arity, 이름, 기타 속성을 가진 임퍼서네이터 프로시저를 반환해요. 임퍼서네이터 프로시저가 적용되면, 인자들이 먼저 wrapper-proc에 전달되고(#f가 아닐 때), 그다음 wrapper-proc의 결과들이 proc에 전달돼요. wrapper-procproc의 결과를 처리하는 프로시저를 추가로 공급할 수도 있어요.

wrapper-proc의 arity는 proc의 arity를 포함해야 해요. wrapper-proc의 허용 키워드 인자는 proc의 허용 키워드의 상위집합이어야 해요. wrapper-proc의 필수 키워드 인자는 proc의 필수 키워드의 부분집합이어야 해요.

키워드 없는 애플리케이션에서 wrapper-proc의 결과는 그것에 공급된 값의 수와 최소한 같은 수여야 해요. 공급된 값에 해당하는 값들보다 앞에 추가 결과가 공급될 수 있는데, 패턴은 다음과 같아요:

  • 선택적 프로시저인 result-wrapper-procproc의 결과에 적용될 것 — 그다음
  • 'mark key val의 반복(즉 세 값) — proc 호출이 continuation mark key와 val을 설치하도록 감싸짐.

result-wrapper-proc가 만들어지면, 그것은 proc이 만드는 만큼의 결과를 받아들이는 프로시저여야 하고, 같은 수의 결과를 반환해야 해요. result-wrapper-proc가 공급되지 않으면 proc은 임퍼서네이터 호출에 대해 꼬리 위치에서 호출돼요.

키워드 인자를 포함하는 애플리케이션에서 wrapper-proc는 다른 값들보다 앞서지만 result-wrapper-proc'mark key val 시퀀스(있으면)보다는 뒤에 추가 값을 반환해야 해요. 그 추가 값은 임퍼서네이터에 공급된 키워드 인자들(즉 공급되지 않은 선택적 인자는 세지 않음)을 대체하는 리스트여야 해요. 인자들은 공급된 인자의 키워드들의 정렬 순서대로 정렬돼야 해요.

wrapper-proc#f이면 결과 임퍼서네이터를 적용하는 것은 proc을 적용하는 것과 같아요. wrapper-proc#f이고 prop이 제공되지 않으면 proc이 반환되고 임퍼서네이트되지 않아요.

propprop-val의 쌍(impersonate-procedure의 인자 수는 짝수여야 해요)은 proc의 임퍼서네이터 속성을 추가하거나 덮어써요. 어떤 propimpersonator-prop:application-mark이고 연관된 prop-val이 쌍이면, proc 호출이 (car prop-val)을 mark key로, (cdr prop-val)을 mark value로 하는 with-continuation-mark으로 감싸져요. 게다가 임퍼서네이트된 프로시저 호출의 즉각적인(immediate) continuation 프레임이 (car prop-val)에 대한 값을 포함하면 — 즉 call-with-immediate-continuation-mark이 호출의 continuation에서 (car prop-val)에 대한 값을 만들면 — 그 값도 wrapper-proc 호출 동안 (car prop-val)의 즉각 값으로 mark로 설치돼요(이것은 래핑 임퍼서네이터에 대해 임퍼서네이터의 꼬리 호출이 wrapper-proc 안에서 감지될 수 있게 해요).

Changed in version 6.3.0.5 of package base: Added support for 'mark key val results from wrapper-proc.

> (define (add15 x) (+ x 15))
> (define add15+print
    (impersonate-procedure add15
                           (λ (x)
                             (printf "called with ~s\n" x)
                             (values (λ (res)
                                       (printf "returned ~s\n" res)
                                       res)
                                     x))))
> (add15 27)
42
> (add15+print 27)
called with 27
returned 42
42
> (define-values (imp-prop:p1 imp-prop:p1? imp-prop:p1-get)
    (make-impersonator-property 'imp-prop:p1))
> (define-values (imp-prop:p2 imp-prop:p2? imp-prop:p2-get)
    (make-impersonator-property 'imp-prop:p2))
> (define add15.2 (impersonate-procedure add15 #f imp-prop:p1 11))
> (add15.2 2)
17
> (imp-prop:p1? add15.2)
#t
> (imp-prop:p1-get add15.2)
11
> (imp-prop:p2? add15.2)
#f
> (define add15.3 (impersonate-procedure add15.2 #f imp-prop:p2 13))
> (add15.3 3)
18
> (imp-prop:p1? add15.3)
#t
> (imp-prop:p1-get add15.3)
11
> (imp-prop:p2? add15.3)
#t
> (imp-prop:p2-get add15.3)
13
> (define add15.4 (impersonate-procedure add15.3 #f imp-prop:p1 101))
> (add15.4 4)
19
> (imp-prop:p1? add15.4)
#t
> (imp-prop:p1-get add15.4)
101
> (imp-prop:p2? add15.4)
#t
> (imp-prop:p2-get add15.4)
13
(impersonate-procedure* proc wrapper-proc prop prop-val ... ...)
 → (and/c procedure? impersonator?)
  proc : procedure?
  wrapper-proc : (or/c procedure? #f)
  prop : impersonator-property?
  prop-val : any/c

impersonate-procedure와 같지만, wrapper-proc가 다른 모든 인자보다 앞에 추가 인자를 받아요. 그 추가 인자는 원래 적용된 프로시저 orig-proc예요.

impersonate-procedure*의 결과가 직접 적용되면 orig-proc은 그 결과예요. 결과가 적용 전에 추가로 임퍼서네이트되면 orig-proc은 그 추가 임퍼서네이터예요.

orig-proc 인자는 예를 들어 더 추가된 임퍼서네이터가 덮어쓴 임퍼서네이터 속성을 wrapper-proc이 추출하는 데 유용할 수 있어요. Added in version 6.1.1.5 of package base.

(impersonate-struct v [struct-type] orig-proc redirect-proc ... ...
                    prop prop-val ... ...) → any/c
  v : any/c
  struct-type : struct-type? = unspecified
  orig-proc : (or/c struct-accessor-procedure?
                    struct-mutator-procedure?
                    struct-type-property-accessor-procedure?)
  redirect-proc : (or/c procedure? #f)
  prop : impersonator-property?
  prop-val : any/c

v의 임퍼서네이터를 반환하는데, 임퍼서네이트된 값의 특정 연산을 가로채요. orig-proc들이 가로챌 연산을 나타내고, 대응하는 redirect-proc들이 가로챈 결과를 제공해요. 선택적 struct-type 인자는, 제공되면 v의 표현에 대한 증인(witness)으로 작용하는데, vstruct-type의 인스턴스여야 해요.

redirect-proc의 프로토콜은 대응하는 orig-proc에 따라 달라지는데, selforig-proc이 원래 적용되는 값을 가리켜요:

  • 구조체 필드 접근자: redirect-proc는 두 인자, selforig-procv에 대해 만드는 값 field-v를 받아야 하고, field-v의 대체를 반환해야 해요. 대응하는 필드는 불변이면 안 되고, 필드의 구조체 타입이 현재 inspector로 접근 가능하거나 다른 orig-proc 중 하나가 같은 필드의 구조체 필드 뮤테이터여야 해요.
  • 구조체 필드 뮤테이터: redirect-proc는 두 인자, self와 뮤테이터에 공급된 값 field-v를 받아야 하고, orig-procv에 전파할 field-v의 대체를 반환해야 해요.
  • 속성 접근자: redirect-proc는 구조체 필드 접근자와 같은 프로토콜을 써요. 접근자의 속성은 make-struct-type-property의 두 번째 인자로 'can-impersonate를 주고 만들어졌어야 해요.

redirect-proc#f이면 대응하는 orig-proc은 영향받지 않아요. redirect-proc#f를 주는 것은 그 orig-procv의 표현의 "증인"으로 작용하고 props의 추가를 가능하게 하는 데 유용해요.

propprop-val의 쌍(struct-type이 제공되면 impersonate-struct의 인자 수는 짝수, 그렇지 않으면 홀수여야 해요)은 v의 임퍼서네이터 속성을 추가하거나 덮어써요.

orig-proc은 서로 다른 연산을 나타내야 해요. struct-typeorig-proc도 공급되지 않으면 props도 공급되지 않아야 해요. orig-proc들이 #f redirect-proc만으로 공급되고 props가 공급되지 않으면 v가 반환되고 임퍼서네이트되지 않아요.

어떤 orig-proc이 그 자체로 임퍼서네이터이면, 그 orig-proc이 임퍼서네이트하는 접근자·뮤테이터의 사용은 결과 임퍼서네이트된 구조체에 대해 redirect-proc 전에(접근자 경우) 또는 후에(뮤테이터 경우) vorig-proc을 쓰도록 가로채져요.

Changed in version 6.1.1.2 of package base: Changed first argument to an accessor or mutator redirect-proc from v to self. Changed in version 6.1.1.8: Added optional struct-type argument.

(impersonate-vector vec ref-proc set-proc prop prop-val ... ...)
 → (and/c vector? impersonator?)
  vec : (and/c vector? (not/c immutable?))
  ref-proc : (or/c (vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  set-proc : (or/c (vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  prop : impersonator-property?
  prop-val : any/c

vec의 임퍼서네이터를 반환하는데, vector-refvector-set! 연산을 가로채요.

ref-procset-proc 인자는 둘 다 프로시저이거나 둘 다 #f여야 해요. 둘 다 #f이면 impersonate-vectorvec에 간섭하지 않지만 임퍼서네이터 속성을 붙이는 것을 허용해요.

ref-proc가 프로시저이면 vec, vector-ref에 전달된 인덱스, 주어진 인덱스에 대해 vec에서 vector-ref이 만드는 값을 받아야 하고, 값의 대체를 만들어야 해요. 그것이 임퍼서네이터에서 vector-ref의 결과예요.

set-proc가 프로시저이면 vec, vector-set!에 전달된 인덱스, vector-set!에 전달된 값을 받아야 하고, 값의 대체를 만들어야 해요. 그것이 원래 vec에서 vector-set!과 함께 값의 설치에 쓰여요.

propprop-val의 쌍(impersonate-vector의 인자 수는 홀수여야 해요)은 vec의 임퍼서네이터 속성을 추가하거나 덮어써요. Changed in version 6.9.0.2 of package base: Added non-interposing vector impersonators.

(impersonate-vector* vec ref-proc set-proc prop prop-val ... ...)
 → (and/c vector? impersonator?)
  vec : (and/c vector? (not/c immutable?))
  ref-proc : (or/c (vector? vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  set-proc : (or/c (vector? vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  prop : impersonator-property?
  prop-val : any/c

impersonate-vector와 같지만, ref-procset-proc가 다른 인자들보다 앞에 추가 벡터 인자를 받아요. 그 추가 인자는 간섭을 촉발한 원래 임퍼서네이트된 벡터예요. 추가 벡터 인자는 예를 들어 ref-procset-proc가 더 추가된 임퍼서네이터가 덮어쓴 임퍼서네이터 속성을 추출하는 데 유용할 수 있어요. Added in version 6.9.0.2 of package base.

(impersonate-box box unbox-proc set-proc prop prop-val ... ...)
 → (and/c box? impersonator?)
  box : (and/c box? (not/c immutable?))
  unbox-proc : (box? any/c . -> . any/c)
  set-proc : (box? any/c . -> . any/c)
  prop : impersonator-property?
  prop-val : any/c

box의 임퍼서네이터를 반환하는데, unboxset-box! 연산을 가로채요.

unbox-procboxbox에서 unbox가 만드는 값을 받아야 하고, 대체 값을 만들어야 해요. 그것이 임퍼서네이터에서 unbox의 결과예요.

set-procboxset-box!에 전달된 값을 받아야 하고, 대체 값을 만들어야 해요. 그것이 원래 box에서 set-box!과 함께 값의 설치에 쓰여요.

propprop-val의 쌍(impersonate-box의 인자 수는 홀수여야 해요)은 box의 임퍼서네이터 속성을 추가하거나 덮어써요.

(impersonate-hash hash ref-proc set-proc remove-proc key-proc
                  [clear-proc equal-key-proc] prop prop-val ... ...)
 → (and/c hash? impersonator?)
  hash : (and/c hash? (not/c immutable?))
  ref-proc : (hash? any/c . -> . (values any/c (hash? any/c any/c . -> . any/c)))
  set-proc : (hash? any/c any/c . -> . (values any/c any/c))
  remove-proc : (hash? any/c . -> . any/c)
  key-proc : (hash? any/c . -> . any/c)
  clear-proc : (or/c #f (hash? . -> . any)) = #f
  equal-key-proc : (or/c #f (hash? any/c . -> . any/c)) = #f
  prop : impersonator-property?
  prop-val : any/c

hash의 임퍼서네이터를 반환하는데, hash-ref, hash-set! 또는 hash-set(해당 시), hash-remove 또는 hash-remove!(해당 시), hash-clear 또는 hash-clear!(해당 시, clear-proc#f가 아닐 때) 연산을 가로채요. hash-set, hash-remove, hash-clear가 해시 테이블의 임퍼서네이터에 쓰이면, 결과는 같은 가로챔 프로시저를 가진 임퍼서네이터예요.

게다가 hash-iterate-keyhash-map처럼 테이블에서 키를 추출하는 연산은 key-proc을 써서 테이블에서 추출한 키를 대체해요. hash-iterate-valuehash-values 같은 연산은 암묵적으로 hash-ref를 쓰므로 ref-proc을 통해 가로채져요. hash-ref-key 연산은 ref-prockey-proc을 모두 쓰는데, 전자는 요청된 키를 조회하고 후자는 그 키를 추출해요.

ref-prochashhash-ref에 전달된 키를 받아야 해요. 대체 키와 프로시저를 반환해야 해요. 반환된 프로시저는 반환된 키가 hash-ref를 통해 hash에서 발견된 경우에만 호출되는데, 그 경우 프로시저는 hash, 앞서 반환된 키, 발견된 값을 받아 호출돼요. 반환된 프로시저는 발견된 값의 대체를 반환해야 해요. 반환된 프로시저는 hash-ref-key에 의해 무시돼요.

set-prochash, hash-set! 또는 hash-set에 전달된 키, hash-set! 또는 hash-set에 전달된 값을 받아야 하고, 키의 대체와 값의 대체 두 값을 만들어야 해요. 반환된 키와 값은 원래 hash에서 hash-set! 또는 hash-set과 함께 값의 설치에 쓰여요.

remove-prochashhash-remove! 또는 hash-remove에 전달된 키를 받아야 하고, 키의 대체를 만들어야 해요. 그것이 원래 hash에서 hash-remove! 또는 hash-remove과 함께 (임퍼서네이터가 대체한) 키를 쓰는 매핑 제거에 쓰여요.

key-prochashhash에서 추출된 키(hash-ref-key, hash-iterate-key, 또는 내부적으로 hash-iterate-key를 쓰는 다른 연산에 의해)를 받아야 하고, 키의 대체를 만들어야 해요. 그것이 테이블에서 추출된 키로 보고돼요.

clear-proc#f가 아니면 hash를 인자로 받아야 하고, 그 결과는 무시돼요. clear-proc이 (예외를 발생시키거나 다른 방식으로 이탈하지 않고) 반환한다는 사실이 hash에서 모든 키를 제거할 능력을 부여해요. clear-proc#f이면 임퍼서네이터에서 hash-clear 또는 hash-clear!hash-iterate-keyhash-remove 또는 hash-remove!으로 구현돼요.

equal-key-proc#f가 아니면 hash의 키에 대한 equal?, equal-hash-code, equal-secondary-hash-code 호출에 사실상 간섭해요. equal-key-prochashhash가 매핑하거나 hash-ref 등에 전달된 키를 인자로 받아야 하는데, 후자는 대응하는 ref-proc 등이 조정했을 수 있어요. 결과는 키를 해시·비교할 필요에 따라 equal?, equal-hash-code, equal-secondary-hash-code에 전달되는 값이에요. hash-set! 또는 hash-set의 경우 equal-key-proc에 전달되는 키는 향후 조회를 위해 해시 테이블에 저장된 것이에요.

hash-iterate-value, hash-map, hash-for-each 함수는 hash-iterate-keyhash-ref의 조합을 써요. key-proc이 만든 키가 hash-ref를 통해 값을 만들지 못하면 exn:fail:contract 예외가 발생해요.

propprop-val의 쌍은 hash의 임퍼서네이터 속성을 추가하거나 덮어써요.

불변 해시 테이블의 경우, 두 임퍼서네이트된 해시 테이블은 그들의 가로챔 프로시저가 원래 같은 impersonate-hash 또는 chaperone-hash 호출로 해시 테이블에 붙었고(hash-set, hash-remove, hash-clear로 전파됐을 수 있음), 첫 해시 테이블의 내용이 두 번째 해시 테이블의 impersonator-of?인 한, (impersonator-of? 목적상) "같은 값"으로 센다.

Changed in version 6.3.0.11 of package base: Added the equal-key-proc argument.

(impersonate-channel channel get-proc put-proc prop prop-val ... ...)
 → (and/c channel? impersonator?)
  channel : channel?
  get-proc : (channel? . -> . (values channel? (any/c . -> . any/c)))
  put-proc : (channel? any/c . -> . any/c)
  prop : impersonator-property?
  prop-val : any/c

channel의 임퍼서네이터를 반환하는데, channel-getchannel-put 연산을 가로채요.

get-proc 생성자는 channel-get이나 채널에서 결과를 가져오는 다른 연산(채널에 대한 sync 같은)에서 호출돼요. get-proc는 두 값을 반환해야 해요: channel의 임퍼서네이터인 채널, 그리고 채널의 내용을 검사하는 데 쓰는 프로시저.

put-procchannelchannel-put에 전달된 값을 받아야 하고, 대체 값을 만들어야 해요. 그것이 원래 channel에서 channel-put과 함께 채널로 값을 보내는 데 쓰여요.

propprop-val의 쌍(impersonate-channel의 인자 수는 홀수여야 해요)은 channel의 임퍼서네이터 속성을 추가하거나 덮어써요.

(impersonate-prompt-tag prompt-tag handle-proc abort-proc
                        [cc-guard-proc callcc-impersonate-proc comp-guard-proc]
                        prop prop-val ... ...)
 → (and/c continuation-prompt-tag? impersonator?)
  prompt-tag : continuation-prompt-tag?
  handle-proc : procedure?
  abort-proc : procedure?
  cc-guard-proc : procedure? = values
  callcc-impersonate-proc : (procedure? . -> . procedure?) = (lambda (p) p)
  comp-guard-proc : procedure? = values
  prop : impersonator-property?
  prop-val : any/c

prompt-tag의 임퍼서네이터를 반환하는데, call-with-continuation-promptabort-current-continuation 연산을 가로채요.

handle-proc는 continuation prompt의 핸들러가 받을 값을 받아야 하고, 핸들러에 전달될 대체 값을 만들어야 해요.

abort-procabort-current-continuation에 전달된 값을 받아야 하고, 적절한 프롬프트로 중단될(abort) 대체 값을 만들어야 해요.

cc-guard-proc는 프롬프트로 구분된 continuation을 대체하기 위해 비조합(non-composable) continuation이 적용되는 경우에 call-with-continuation-prompt이 만드는 값을 받아야 하지만, abort-current-continuation이 나중에 프롬프트로 구분된 continuation을 중단하는 데 쓰이지 않는 경우에만(그 경우 abort-proc이 쓰임) 그래요.

callcc-impersonate-proccall-with-current-continuation으로 포착한 continuation의 결과를 임퍼서네이트된 프롬프트 태그로 가드는 프로시저를 받아야 해요. callcc-impersonate-proc은 포착된 continuation이 적용될 때 (continuation barrier 아래에서) 적용되어, 구분 프롬프트에 특화된 가드 함수(처음에는 values)를 세밀화해요. 이 프롬프트 특화 가드는 궁극적으로 구분 프롬프트에서 유효한 어떤 cc-guard-proc과도 결합되고, cc-guard-proc이 쓰이지 않는 경우(즉 abort-current-continuation이 프롬프트로 중단하는 데 쓰일 때)에는 쓰이지 않아요. 특수한 경우로, 적용 시점의 구분 프롬프트가 스레드의 내장 초기 프롬프트이면 callcc-impersonate-proc은 무시돼요(초기 프롬프트의 결과가 무시된다는 근거로 부분적으로).

comp-guard-proc 프로시저는 cc-guard-proc과 비슷하지만, 임퍼서네이트된 프롬프트로 포착한 조합(composable) continuation의 결과에 적용돼요. comp-guard-procvalues가 아닌 프로시저이면, 임퍼서네이트된 프롬프트로 포착한 조합 continuation은 그 호출 지점에 대해 꼬리 위치에서 적용되지 않는데, continuation의 결과가 comp-guard-proc에 전달되기 때문이에요.

propprop-val의 쌍(impersonate-prompt-tag의 인자 수는 홀수여야 해요)은 prompt-tag의 임퍼서네이터 속성을 추가하거나 덮어써요.

> (define tag
    (impersonate-prompt-tag
     (make-continuation-prompt-tag)
     (lambda (n) (* n 2))
     (lambda (n) (+ n 1))))
> (call-with-continuation-prompt
    (lambda ()
      (abort-current-continuation tag 5))
    tag
    (lambda (n) n))
12

Changed in version 9.2.0.6 of package base: Added the comp-guard-proc argument.

(impersonate-continuation-mark-key key get-proc set-proc
                                   prop prop-val ... ...)
 → (and/c continuation-mark? impersonator?)
  key : continuation-mark-key?
  get-proc : procedure?
  set-proc : procedure?
  prop : impersonator-property?
  prop-val : any/c

key의 임퍼서네이터를 반환하는데, with-continuation-markcontinuation-mark-set->list 같은 continuation mark 접근자를 가로채요.

get-proc는 continuation mark에 붙은 값을 받아야 하고, continuation mark 접근자가 반환할 대체 값을 만들어야 해요.

set-procwith-continuation-mark에 전달된 값을 받아야 하고, continuation 프레임에 붙을 대체 값을 만들어야 해요.

propprop-val의 쌍(impersonate-continuation-mark-key의 인자 수는 홀수여야 해요)은 key의 임퍼서네이터 속성을 추가하거나 덮어써요.

> (define mark-key
    (impersonate-continuation-mark-key
     (make-continuation-mark-key)
     (lambda (l) (map char-upcase l))
     (lambda (s) (string->list s))))
> (with-continuation-mark mark-key "quiche"
    (continuation-mark-set-first
     (current-continuation-marks)
     mark-key))
'(#\Q #\U #\I #\C #\H #\E)

prop:impersonator-of

prop:impersonator-of : struct-type-property?

임퍼서네이터를 나타내는 구조체에서 임퍼서네이트된 값을 추출하는 프로시저를 공급하는 구조체 타입 속성(Structure Type Properties 참고)이에요. 이 속성은 impersonator-of?뿐 아니라 equal?에도 쓰여요.

속성 값은 한 인자의 프로시저여야 하는데, 그 인자는 속성을 가진 구조체 타입의 구조체예요. 결과는 #f일 수 있는데 구조체가 임퍼서네이터를 나타내지 않음을 표시하고, 그 외에는 원래 구조체가 임퍼서네이터인 값(그래서 원래 구조체는 결과 값의 impersonator-of?이고 equal?)이에요. 결과 값은 원래 구조체와 같은 prop:impersonator-of 속성 값과 prop:equal+hash 속성 값을 가져야 하고, 속성 값들은 같은 구조체 타입에서 상속받아야 해요(이것은 impersonator-of?equal? 사이의 일관성을 보장해요).

prop:impersonator-of 속성을 가진 구조체에 적용되는 임퍼서네이터 속성 술어와 접근자는 먼저 즉각적인 구조체의 속성을 확인하고, 발견되지 않으면 prop:impersonator-of 프로시저가 만든 값을 (재귀적으로) 확인해요.

Changed in version 6.1.1.8 of package base: Made impersonator property predicates and accessors sensitive to prop:impersonator-of.

prop:authentic

prop:authentic : struct-type-property?

구조체 타입을 정통(authentic)으로 선언하는 구조체 타입 속성이에요. 속성과 연관된 값은 무시돼요. 속성 자체의 존재가 구조체 타입을 정통으로 만들어요.

정통 구조체 타입의 인스턴스는 impersonate-struct로 임퍼서네이트되거나 chaperone-struct로 셔프런될 수 없어요. 그 결과, 정통 구조체 타입의 인스턴스는 플랫 계약(flat contract)일 때만 계약(struct/c 참고)을 받을 수 있어요.

구조체 타입을 정통으로 선언하면 원치 않는 구조체 임퍼서네이션을 막을 수 있지만, 노출된 구조체 타입은 일반적으로 계약을 용이하게 하기 위해 임퍼서네이터나 셔프런을 지원해야 해요. 구조체 타입을 정통으로 선언하면 구조체 술어·선택자·뮤테이터의 성능도 약간 향상될 수 있는데, 이는 라이브러리 안에서 비공개이고 자주 쓰는 데이터 구조에 적절할 수 있어요.

Added in version 6.9.0.4 of package base.

14.5.2 셔프런 생성자 (Chaperone Constructors)

(chaperone-procedure proc wrapper-proc prop prop-val ... ...)
 → (and/c procedure? chaperone?)
  proc : procedure?
  wrapper-proc : (or/c procedure? #f)
  prop : impersonator-property?
  prop-val : any/c

impersonate-procedure와 같지만, wrapper-proc에 공급된 각 값에 대해, 대응하는 결과는 (chaperone-of?의 의미에서) 공급된 값과 같거나 그것의 셔프런이어야 해요. 셔프런된 값들보다 앞에 오는 추가 결과(있으면)는 proc이 만드는 만큼의 결과를 받아들이는 프로시저여야 하고, 같은 수의 결과를 반환해야 하는데, 각 결과는 대응하는 원래 결과와 같거나 그것의 셔프런이에요.

키워드 인자를 포함하는 애플리케이션에서 wrapper-proc는 다른 값들보다 앞서지만 결과 셔프런 프로시저(있으면)보다는 뒤에 추가 값을 반환해야 해요. 그 추가 값은 셔프런 프로시저에 공급된 키워드 인자들(즉 공급되지 않은 선택적 인자는 세지 않음)의 셔프런 리스트여야 해요. 인자들은 공급된 인자의 키워드들의 정렬 순서대로 정렬돼야 해요.

(chaperone-procedure* proc wrapper-proc prop prop-val ... ...)
 → (and/c procedure? chaperone?)
  proc : procedure?
  wrapper-proc : (or/c procedure? #f)
  prop : impersonator-property?
  prop-val : any/c

chaperone-procedure와 같지만, impersonate-procedure*처럼 wrapper-proc가 추가 인자를 받아요. Added in version 6.1.1.5 of package base.

(chaperone-struct v [struct-type] orig-proc redirect-proc ... ...
                  prop prop-val ... ...) → any/c
  v : any/c
  struct-type : struct-type? = unspecified
  orig-proc : (or/c struct-accessor-procedure?
                    struct-mutator-procedure?
                    struct-type-property-accessor-procedure?
                    (lambda (proc) (eq? proc struct-info)))
  redirect-proc : (or/c procedure? #f)
  prop : impersonator-property?
  prop-val : any/c

impersonate-struct와 같지만, 다음 세밀화가 있어요. selforig-proc이 원래 적용되는 값을 가리켜요:

  • orig-proc으로 구조체 필드 접근자를 가지면, redirect-proc는 두 인자, selforig-procv에 대해 만드는 값 field-v를 받아야 하고, field-v의 셔프런을 반환해야 해요. 대응하는 필드는 불변이어도 돼요.
  • orig-proc으로 구조체 필드 뮤테이터를 가지면, redirect-proc는 두 인자, self와 뮤테이터에 공급된 값 field-v를 받아야 하고, orig-procv에 전파할 field-v의 셔프런을 반환해야 해요.
  • orig-proc으로 속성 접근자를 공급할 수 있고, 그 속성은 'can-impersonate로 만들어질 필요가 없어요. 대응하는 redirect-proc은 구조체 필드 접근자와 같은 프로토콜을 써요.
  • orig-proc으로 struct-info를 가지면, 대응하는 redirect-proc은 두 값, 즉 v에 대한 struct-info의 결과를 받아야 하고, 각 값을 반환하거나 각 값의 셔프런을 반환해야 해요. struct-info가 첫 번째 인자로 #f를 반환하면 redirect-proc은 호출되지 않아요. orig-procstruct-type이나 다른 orig-proc이 공급된 경우에만 struct-info일 수 있어요.
  • 임퍼서네이터인 어떤 접근자·뮤테이터 orig-proc은 구체적으로 셔프런이어야 해요.

orig-proc으로 속성 접근자를 공급하면, 접근자·뮤테이터·구조체 타입을 공급하는 것과 마찬가지로 prop 인자가 가능해져요.

Changed in version 6.1.1.2 of package base: Changed first argument to an accessor or mutator redirect-proc from v to self. Changed in version 6.1.1.8: Added optional struct-type argument.

(chaperone-vector vec ref-proc set-proc prop prop-val ... ...)
 → (and/c vector? chaperone?)
  vec : vector?
  ref-proc : (or/c (vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  set-proc : (or/c (vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  prop : impersonator-property?
  prop-val : any/c

impersonate-vector와 같지만, 불변 벡터를 지원해요. ref-proc 프로시저는 원래 값과 같은 값 또는 그것의 셔프런을 만들어야 하고, set-proc은 주어진 값 또는 그것의 셔프런을 만들어야 해요. vec이 불변이면 set-proc은 쓰이지 않아요.

(chaperone-vector* vec ref-proc set-proc prop prop-val ... ...)
 → (and/c vector? chaperone?)
  vec : vector?
  ref-proc : (or/c (vector? vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  set-proc : (or/c (vector? vector? exact-nonnegative-integer? any/c . -> . any/c) #f)
  prop : impersonator-property?
  prop-val : any/c

chaperone-vector와 같지만, impersonate-vector*처럼 ref-procset-proc가 추가 인자를 받아요. Added in version 6.9.0.2 of package base.

(chaperone-box box unbox-proc set-proc prop prop-val ... ...)
 → (and/c box? chaperone?)
  box : box?
  unbox-proc : (box? any/c . -> . any/c)
  set-proc : (box? any/c . -> . any/c)
  prop : impersonator-property?
  prop-val : any/c

impersonate-box와 같지만, 불변 박스를 지원해요. unbox-proc 프로시저는 원래 값과 같은 값 또는 그것의 셔프런을 만들어야 하고, set-proc은 주어진 값과 같은 값 또는 그것의 셔프런을 만들어야 해요. box이 불변이면 set-proc은 쓰이지 않아요.

(chaperone-hash hash ref-proc set-proc remove-proc key-proc
                [clear-proc equal-key-proc] prop prop-val ... ...)
 → (and/c hash? chaperone?)
  hash : hash?
  ref-proc : (hash? any/c . -> . (values any/c (hash? any/c any/c . -> . any/c)))
  set-proc : (hash? any/c any/c . -> . (values any/c any/c))
  remove-proc : (hash? any/c . -> . any/c)
  key-proc : (hash? any/c . -> . any/c)
  clear-proc : (or/c #f (hash? . -> . any)) = #f
  equal-key-proc : (or/c #f (hash? any/c . -> . any/c)) = #f
  prop : impersonator-property?
  prop-val : any/c

impersonate-hash와 같지만, 주어진 함수들에 제약이 있고 불변 해시를 지원해요. ref-proc 프로시저는 발견된 값 또는 그것의 셔프런을 반환해야 해요. set-proc 프로시저는 두 값을 만들어야 해요: 주어진 키 또는 그것의 셔프런, 그리고 주어진 값 또는 그것의 셔프런. remove-proc, key-proc, equal-key-proc 프로시저는 주어진 키 또는 그것의 셔프런을 만들어야 해요. Changed in version 6.3.0.11 of package base: Added the equal-key-proc argument.

(chaperone-struct-type struct-type struct-info-proc
                        make-constructor-proc guard-proc
                        prop prop-val ... ...)
 → (and/c struct-type? chaperone?)
  struct-type : struct-type?
  struct-info-proc : procedure?
  make-constructor-proc : (procedure? . -> . procedure?)
  guard-proc : procedure?
  prop : impersonator-property?
  prop-val : any/c

struct-type과 같은 셔프런된 값을 반환하되, 셔프런된 구조체 타입에서 struct-type-infostruct-type-make-constructor 연산을 가로채요. 게다가 셔프런된 구조체 타입의 하위 타입으로 새 구조체 타입이 만들어질 때, guard-proc이 하위 타입 인스턴스 생성에 추가 가드로 간섭돼요.

struct-info-procstruct-type-infostruct-type에 대한 결과인 8개 인자를 받아야 해요. 각각이 대응하는 인자와 같거나 그것의 셔프런인 8개 값을 반환해야 해요. 그 8개 값이 셔프런된 구조체 타입에 대한 struct-type-info의 결과로 쓰여요.

make-constructor-procstruct-type-make-constructorstruct-type에 대해 만든 생성자인 단일 프로시저 인자를 받아야 해요. 그 프로시저와 같거나 그것의 셔프런을 반환해야 하고, 그것이 셔프런된 구조체 타입에서 struct-type-make-constructor의 결과로 쓰여요.

guard-procmake-struct-type에 대한 가드 인자와 같아요: struct-type에 대한 생성자보다 하나 많은 인자를 받아야 하는데, 마지막 인자는 인스턴스화된 구조체 타입의 이름이에요. 생성자가 필요로 하는 만큼의 값(즉 마지막을 제외한 각 인자에 대해 한 값)을 반환해야 하고, 각 반환 값은 대응하는 인자와 같거나 그것의 셔프런이어야 해요. guard-proc은 셔프런된 구조체 타입의 하위 타입이 만들어질 때 생성자 가드로 추가돼요.

propprop-val의 쌍(chaperone-struct-type의 인자 수는 짝수여야 해요)은 struct-type의 임퍼서네이터 속성을 추가하거나 덮어써요.

(chaperone-evt evt proc prop prop-val ... ...)
 → (and/c evt? chaperone?)
  evt : evt?
  proc : (evt? . -> . (values evt? (any/c . -> . any/c)))
  prop : impersonator-property?
  prop-val : any/c

evt과 같은 셔프런된 값을 반환하되, 결과가 sync 같은 함수로 동기화될 때 proc을 이벤트 생성자로 가져요.

proc 생성자는 guard-evt에 전달되는 프로시저와 비슷하게 동기화 시 호출되는데, 단 procevt이 주어져요. proc은 두 값을 반환해야 해요: evt의 셔프런인 동기화 가능한 이벤트, 그리고 선택에서 그 이벤트가 선택되면 그 결과를 검사하는 데 쓰는 프로시저. 후자 프로시저는 evt의 결과를 받아들이고, 그 값의 셔프런을 반환해야 해요.

propprop-val의 쌍(chaperone-evt의 인자 수는 짝수여야 해요)은 evt의 임퍼서네이터 속성을 추가하거나 덮어써요.

결과는 인자 evtchaperone-of?예요. 그러나 evt이 스레드, 세마포어, 입력 포트, 출력 포트, 또는 will executor이면 결과는 그런 것으로 인식되지 않아요. 예를 들어 chaperone-evt의 결과에 적용되는 thread?는 항상 #f를 만들어요.

(chaperone-channel channel get-proc put-proc prop prop-val ... ...)
 → (and/c channel? chaperone?)
  channel : channel?
  get-proc : (channel? . -> . (values channel? (any/c . -> . any/c)))
  put-proc : (channel? any/c . -> . any/c)
  prop : impersonator-property?
  prop-val : any/c

impersonate-channel과 같지만, get-procput-proc 프로시저에 제약이 있어요.

get-proc는 두 값을 반환해야 해요: channel의 셔프런인 채널, 그리고 채널의 내용을 검사하는 데 쓰는 프로시저. 후자 프로시저는 원래 값 또는 그것의 셔프런을 반환해야 해요.

put-proc는 채널로 통신되는 원래 값 또는 그것의 셔프런인 대체 값을 만들어야 해요.

propprop-val의 쌍(chaperone-channel의 인자 수는 홀수여야 해요)은 channel의 임퍼서네이터 속성을 추가하거나 덮어써요.

(chaperone-prompt-tag prompt-tag handle-proc abort-proc
                      [cc-guard-proc callcc-chaperone-proc comp-guard-proc]
                      prop prop-val ... ...)
 → (and/c continuation-prompt-tag? chaperone?)
  prompt-tag : continuation-prompt-tag?
  handle-proc : procedure?
  abort-proc : procedure?
  cc-guard-proc : procedure? = values
  callcc-chaperone-proc : (procedure? . -> . procedure?) = (lambda (p) p)
  comp-guard-proc : procedure? = values
  prop : impersonator-property?
  prop-val : any/c

impersonate-prompt-tag와 같지만, 셔프런된 값을 만들어요. handle-proc 프로시저는 원래 값과 같거나 그것들의 셔프런인 값을 만들어야 하고, abort-proc은 주어진 값과 같거나 그것들의 셔프런인 값을 만들어야 하고, cc-guard-proc은 원래 결과 값과 같거나 그것들의 셔프런인 값을 만들어야 하고, callcc-chaperone-proc은 주어진 프로시저와 같거나 그것의 셔프런인 프로시저를 만들어야 하고, comp-guard-proc은 원래 결과 값과 같거나 그것들의 셔프런인 값을 만들어야 해요.

> (define bad-chaperone
    (chaperone-prompt-tag
     (make-continuation-prompt-tag)
     (lambda (n) (* n 2))
     (lambda (n) (+ n 1))))
> (call-with-continuation-prompt
    (lambda ()
      (abort-current-continuation bad-chaperone 5))
    bad-chaperone
    (lambda (n) n))
abort-current-continuation: non-chaperone result; received a
prompt-abort argument that is not a chaperone of the
original prompt-abort argument
  original: 5
  received: 6
> (define good-chaperone
    (chaperone-prompt-tag
     (make-continuation-prompt-tag)
     (lambda (n) (if (even? n) n (error "not even")))
     (lambda (n) (if (even? n) n (error "not even")))))
> (call-with-continuation-prompt
    (lambda ()
      (abort-current-continuation good-chaperone 2))
    good-chaperone
    (lambda (n) n))
2

Changed in version 9.2.0.6 of package base: Added the comp-guard-proc argument.

(chaperone-continuation-mark-key key get-proc set-proc
                                  prop prop-val ... ...)
 → (and/c continuation-mark-key? chaperone?)
  key : continuation-mark-key?
  get-proc : procedure?
  set-proc : procedure?
  prop : impersonator-property?
  prop-val : any/c

impersonate-continuation-mark-key와 같지만, 셔프런된 값을 만들어요. get-proc 프로시저는 원래 값과 같은 값 또는 그것의 셔프런을 만들어야 하고, set-proc은 주어진 값과 같은 값 또는 그것의 셔프런을 만들어야 해요.

> (define bad-chaperone
    (chaperone-continuation-mark-key
     (make-continuation-mark-key)
     (lambda (l) (map char-upcase l))
     string->list))
> (with-continuation-mark bad-chaperone "timballo"
    (continuation-mark-set-first
     (current-continuation-marks)
     bad-chaperone))
with-continuation-mark: non-chaperone result; received a
value that is not a chaperone of the original value
  original: "timballo"
  received: '(#\t #\i #\m #\b #\a #\l #\l #\o)
> (define (checker s)
    (if (> (string-length s) 5)
        s
        (error "expected string of length at least 5")))
> (define good-chaperone
    (chaperone-continuation-mark-key
     (make-continuation-mark-key)
     checker
     checker))
> (with-continuation-mark good-chaperone "zabaione"
    (continuation-mark-set-first
     (current-continuation-marks)
     good-chaperone))
"zabaione"

14.5.3 임퍼서네이터 속성 (Impersonator Properties)

(make-impersonator-property name)
 → impersonator-property?
    (-> any/c boolean?)
    (->* (impersonator?) (any/c) any)
  name : symbol?

새 임퍼서네이터 속성을 만들고 세 값을 반환해요:

  • 임퍼서네이터 속성 기술자 — impersonate-procedure, chaperone-procedure 및 다른 임퍼서네이터 생성자와 함께 씀.
  • 임퍼서네이터 속성 술어 프로시저 — 임의 값을 받아, 그 값이 속성에 대한 값을 가진 임퍼서네이터이면 #t, 그렇지 않으면 #f를 반환해요.
  • 임퍼서네이터 속성 접근자 프로시저 — 임퍼서네이터에 대해 속성과 연관된 값을 반환해요. 접근자에 주어진 값이 임퍼서네이터가 아니거나 속성에 대한 값이 없으면(즉 대응하는 임퍼서네이터 속성 술어가 #f를 반환하면), 선택자에 대한 두 번째 선택적 인자가 그 응답을 결정해요: 두 번째 인자가 제공되지 않으면 exn:fail:contract 예외가 발생하고, 두 번째 인자가 프로시저이면 0 인자로 두 번째 인자를 꼬리 호출하며, 그렇지 않으면 두 번째 인자가 반환돼요.
(impersonator-property? v) → boolean?
  v : any/c

v가 임퍼서네이터 속성 기술자 값이면 #t, 그렇지 않으면 #f를 반환해요.

(impersonator-property-predicate-procedure? v) → boolean?
  v : any/c

vmake-impersonator-property가 만든 술어 프로시저이면 #t, 그렇지 않으면 #f를 반환해요. Added in version 9.1.0.6 of package base.

(impersonator-property-accessor-procedure? v) → boolean?
  v : any/c

vmake-impersonator-property가 만든 접근자 프로시저이면 #t, 그렇지 않으면 #f를 반환해요.

impersonator-prop:application-mark : impersonator-property?

impersonate-procedurechaperone-procedure가 인식하는 임퍼서네이터 속성이에요.

더 알아보기