난수 생성
난수 생성 (Random Generation)
계약(contract)에 맞는 값을 무작위로 생성하거나, 값을 깨뜨려 계약을 위반시키는(contract-exercise) 도구들을 살펴볼게요. 프로퍼티 기반 테스트와 함께 쓰면 유용해요.
출처: Racket Reference
본문
procedure
(contract-random-generate ctc [fuel fail]) → any/c
ctc : contract?
fuel : 5 = exact-nonnegative-integer?
fail : (or/c #f (-> any) (-> boolean? any)) = #f
계약과 일치할 값을 무작위로 생성하려 시도해요. fuel 인자는 생성기가 계약과 일치하는 값을 만들려고 얼마나 애쓰는지를 제한하며, 결과 값의 크기에 대한 대략적인 한계예요.
생성기는 값을 생성하지 못할 수 있어요. 어떤 계약에는 대응하는 생성기가 없거나(예: 모든 술어가 생성기를 가지는 건 아님) fuel이 부족해서지요. 어느 경우든 fail 함수가 호출돼요. fail이 인자를 받으면, ctc에 대한 생성기가 없을 때 #t로 호출되고, 생성기는 있지만 생성기가 결국 contract-random-generate-fail을 돌려줬을 때는 #f로 호출돼요.
예시를 볼게요:
> (for/list ([i (in-range 10)])
(contract-random-generate (or/c integer? #f)))
'(#f #f #f #f -81 #f #f #f -59.0 2147483647.0)
패키지 base의 버전 6.1.1.5에서 변경됨: fail이 boolean을 받을 수 있게 됐어요.
procedure
(contract-exercise [#:fuel fuel
#:shuffle? shuffle?]
val ...+) → void?
fuel : exact-nonnegative-integer? = 10
shuffle? : any/c = #f
val : any/c
val들이 (있다면) 자신의 계약을 깨뜨리도록 만드려고 시도해요.
value-contract를 사용해 val 중 어느 것에 계약이 있는지 판별하고, 계약이 있는 것들에 대해서는 계약 모양에 대한 정보를 사용해 값을 찔러보고(probe) 건드려봐요(poke). 예를 들어 값이 함수라면, 계약을 사용해 그 값에 어떤 인자를 넘겨야 하는지 알려줘요.
fuel 인자는 contract-exercise가 값을 깨뜨리려 얼마나 애쓰는지를 결정해요. 그것은 운동(exercise) 반복 횟수와 운동 중 생성되는 중간 값의 크기를 모두 제어해요.
shuffle? 인자는 contract-exercise가 운동 순서를 무작위로 섞을지 여부를 제어해요. shuffle?가 #f가 아니면, contract-exercise는 각 운동 반복에서 계약들의 순서를 섞어요.
예시를 볼게요:
> (define/contract (returns-false x)
(-> integer? integer?)
; does not obey its contract
#f)
> (contract-exercise returns-false)
returns-false: broke its own contract
promised: integer?
produced: #f
in: the range of
(-> integer? integer?)
contract from: (function returns-false)
blaming: (function returns-false)
(assuming the contract is correct)
at: eval:2:0
> (define/contract (calls-its-argument-with-eleven f)
(-> (-> integer? integer?) boolean?)
; f returns an integer, but
; we're supposed to return a boolean
(f 11))
> (contract-exercise calls-its-argument-with-eleven)
calls-its-argument-with-eleven: broke its own contract
promised: boolean?
produced: 11
in: the range of
(-> (-> integer? integer?) boolean?)
contract from:
(function calls-its-argument-with-eleven)
blaming: (function calls-its-argument-with-eleven)
(assuming the contract is correct)
at: eval:4:0
패키지 base의 버전 7.0.0.18에서 변경됨: shuffle? 선택 인자가 추가됐어요.
procedure
(contract-random-generate/choose c fuel) → (or/c #f (-> c))
c : contract?
fuel : exact-nonnegative-integer?
이 함수는 contract-random-generate와 같지만, 자신이 가진 하위 계약(sub-contract)에 기반해 값을 생성하는 컴비네이터와 함께 쓰기 위한 것이에요. contract-random-generate(와 contract-exercise)가 생성기를 만들 때 호출해야 해요. 더 정확히 말하면, contract-random-generate/choose는 build-contract-property, build-chaperone-contract-property, build-flat-contract-property의 generate와 exercise 인자에서만, 그리고 generate(와 exercise) 호출의 동적 범위 동안에만 사용할 수 있어요. 즉 c와 fuel 인자를 받은 뒤 썽크(또는 운동자 exerciser)를 돌려주기 전 사이에서 말이에요.
contract-random-generate/choose는 결코 실패하지 않지만, 둘러싸는 호출이나 원래의 contract-random-generate 호출로 탈출할 수는 있어요.
그것은 여러 가능한 생성 전략 중 하나를 고르므로, 실제로 c에 연결된 생성기를 사용하지 않을 수도 있어요. 대신 contract-random-generate-stash를 통해 알고 있는 c와 일치하는 우회(shash) 값으로 보관된 값을 사용할 수도 있어요.
패키지 base의 버전 6.1.1.5에서 추가됨.
value
contract-random-generate-fail : contract-random-generate-fail?
생성기가 값을 생성하는 데 실패했음을 나타내는 데 쓰이는 원자 값이에요.
패키지 base의 버전 6.1.1.5에서 추가됨.
procedure
(contract-random-generate-fail? v) → boolean?
v : any/c
contract-random-generate-fail을 알아보는 술어예요.
패키지 base의 버전 6.1.1.5에서 추가됨.
procedure
(contract-random-generate-env? v) → boolean?
v : any/c
계약 생성 환경(contract generation environment)을 알아봐요.
패키지 base의 버전 6.1.1.5에서 추가됨.
procedure
(contract-random-generate-stash env c v) → void?
env : contract-random-generate-env?
c : contract?
v : c
이 함수는 테스트 중인 프로그램이 계약 생성 중에 공급하는 값으로 호출해야 해요. 예를 들어 (-> (-> integer? integer?) integer?)가 생성될 때, 그 인자 함수를 호출할 수 있어요. 그 인자 함수가 정수를 돌려주면, 그 정수를 contract-random-generate-stash 호출로 저장해서 다른 정수 생성기가 사용할 수 있게 해야 해요.
패키지 base의 버전 6.1.1.5에서 추가됨.
procedure
(contract-random-generate-get-current-environment)
→ contract-random-generate-env?
현재 생성에 사용 중인 환경을 돌려줘요. 이 함수는 계약 생성의 동적 범위 동안에만 호출할 수 있어요. 계약 생성기의 구성 중에 잡아둔 뒤, 생성이 진행되는 동안 contract-random-generate-stash와 함께 사용하기 위한 것이에요.
패키지 base의 버전 6.1.1.5에서 추가됨.