3
votes

I have written a complimentary-multiply-with-carry PRNG in Racket. I want to use provide to restrict access only to certain functions within my library, and to impose contracts on them. Using the Racket Documentation (linked above), I have put the following code at the top of my file to that end:

(require data/queue)
(provide 
 (contract-out
  (make-cmwc-gen (-> (listof integer?) integer? integer? integer? procedure?))
  (make-default-cmwc-gen (-> integer? procedure?))
  (make-cmwc-gen-raw (-> queue? integer? integer? integer? procedure?))
  (init-cmwc-seed (-> integer? queue?)))) 

But when I run the file in DrRacket, I get the following error:

. contract-out: not a provide sub-form in: (contract-out (make-cmwc-gen (-> (listof 
integer?) integer? integer? integer? procedure?)) (make-default-cmwc-gen (-> integer?   
procedure?)) (make-cmwc-gen-raw (-> queue? integer? integer? integer? procedure?)) 
(init-cmwc-seed (-> integer? queue?)))

The code throws no errors and otherwise works when run in DrRacket without the above code inserted.

What is the proper way to restrict access only to certain functions outside of a source file as well as enforcing their contracts in Racket?

1
Which version of Racket are you using? contract-out was added in September, so if you're using it in a version older than 5.2 it won't work. Also, if you can't upgrade for some reason try using provide/contract.Asumu Takikawa
I believe you are correct. I copied a sample program from the racket docs and it didn't work. Further, my version is 5.1.3 . I know that contracts have been enforced prior to 5.2, though. How were they enforced in 5.1.3?djhaskin987

1 Answers

7
votes

contract-out is new, and introduced in Racket 5.2. If you're using Racket < 5.2, you can still use provide/contract:

Example:

#lang racket
(provide/contract [f (-> number? number?)])

(define (f x) 42)

In Racket 5.2, contract-out is preferred because the elements in the contract can be defined after the contract. That is, if you try something like this in the old system,

#lang racket
;; The following will fail since the contract definition doesn't know
;; about p? at the point of its definition.
(provide/contract [f (-> p? p?)])

(define p? number?)
(define (f x) 42)

then it'd fail, because p? is defined after the contract.

In contrast, contract-out works without needing to rearrange definitions:

#lang racket
(provide (contract-out [f (-> p? p?)]))

(define p? number?)
(define (f x) 42)