Maybe dynamic/c isn't clear enough... its definition is pretty short: (define (dynamic/c pre parameter post) (define pre-ctc (coerce-contract 'pre pre)) (define post-ctc (coerce-contract 'post post)) (make-contract #:name (build-compound-type-name 'dynamic pre-ctc parameter post-ctc) #:projection (λ (b) (define pre-proj ((contract-projection pre-ctc) b)) (define post-proj ((contract-projection post-ctc) b)) (λ (x) (define dyn-proj ((contract-projection (coerce-contract 'dynamic (parameter))) b)) (post-proj (dyn-proj (pre-proj x)))))))
The system provides pre and post, so it can offer protection to the coercion as well as receive protection FROM the coercion. But the coercion comes from a parameter which is exposed to the user. The one I use in the web-server is: (dynamic/c any/c current-response/c response?) where response? is the data structure predicate that the internal plumbing uses. Jay On Mon, Dec 6, 2010 at 9:51 AM, Jay McCarthy <jay.mccar...@gmail.com> wrote: > That's why dynamic/c has a pre/c and post/c. Before it uses the user's > contract, it applies pre/c. After it applies post/c. This ensures that the > user's contract actually coerces to a response? > > Jay > > > On Mon, Dec 6, 2010 at 9:25 AM, Robby Findler <ro...@eecs.northwestern.edu > > wrote: > >> On Mon, Dec 6, 2010 at 9:23 AM, Jay McCarthy <jay.mccar...@gmail.com> >> wrote: >> > Yes, since I am allowing users to customize the coercion behavior, I >> could >> > either have them provide two functions: a coercion-applies? function and >> a >> > coercion function; OR I could have them just provide the coercion >> function >> > and I will check the answer and re-run it inside of the function body. >> > >> > The other issue is that finding all the places where I should apply the >> > coercion inside the body of the function is difficult, because I need to >> do >> > it at every place where a response/c could flow in (relatively easy) and >> > every place where a response/c could flow out (much hard, esp. with >> > continuations). Contracts on functions are very nice in their ability to >> do >> > stuff to inputs and outputs. >> >> >> I think I need more help to understand the programming problem better. >> Why are your users supplying you a contract that you are using to >> protect your functions? That is how can you use anything about that >> contract to avoid errors in your programs? >> >> Robby >> >> > Jay >> > >> > On Mon, Dec 6, 2010 at 8:19 AM, Matthias Felleisen < >> matth...@ccs.neu.edu> >> > wrote: >> >> >> >> The string->number primitive is probably closer to what Jay wants to >> do. >> >> >> >> The only contract I can think of for string->number is >> >> >> >> ;; Number -> Boolean >> >> (define (string->number-able? x) >> >> (number? (string->number x))) >> >> >> >> So the real problem is a performance problem, which a lazy >> interpretation >> >> of contracts by the compiler might be able to eliminate. >> >> >> >> Is this the true problem Jay -- Matthias >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> On Dec 6, 2010, at 9:45 AM, Robby Findler wrote: >> >> >> >> > Let's be clear here: our inability to enforce projectionness is in no >> >> > way condoning the two coercianlike contracts that you have now >> >> > written. >> >> > >> >> > That said, the only value I see to contracts that only signal errors >> >> > (or do nothing) is that programmers know what to expect from them. >> The >> >> > downsides you mention are well taken, of course. >> >> > >> >> > In this specific case, your message seems slightly confused: >> certainly >> >> > you should be able to use a contract to ensure that the coercion will >> >> > always succeed. Let's assume you have done that and now discuss only >> >> > where the coercing bit of the "contract" goes. Is it in a higher >> order >> >> > position? Is it something that describes an interface to your module >> >> > or can it be considered an internal detail? >> >> > >> >> > As a possible guide by analogy, consider the path-string? Predicate. >> >> > It is the contract on many functions the ultimately is connected to >> >> > some kind of a coercion somehwere buried inside the racket primitives >> >> > for dealing with the filesystem. Is that like what you want to do? If >> >> > so, how would your arguments hold up for that part of our system? >> >> > >> >> > Robby >> >> > >> >> > On Monday, December 6, 2010, Jay McCarthy <jay.mccar...@gmail.com> >> >> > wrote: >> >> >> These contracts are not thrown "at dynamic places". The contract is >> >> >> always at the module boundary/etc, but its meaning if affected by >> the >> >> >> dynamic context of the particular boundary crossing. [1] >> >> >> >> >> >> I'm been thinking about why I want to use contracts for this >> purpose. >> >> >> The alternative is to put an any/c contract in all the places I >> >> >> currently have response/c and as the first thing in all those >> functions call >> >> >> current-any->response [or as the last thing on returns] on the input >> >> >> argument. I would then have to put a note in all the documentation >> of those >> >> >> any/c that it doesn't REALLY accept anything, instead in other >> accepts >> >> >> things that the dynamic current-any->response will turn into a >> response. If >> >> >> the coercion failed, then I would have to throw an error, which be >> purely >> >> >> dynamic with no blame information because it would not be associated >> with a >> >> >> contract boundary. >> >> >> >> >> >> In contrast, using a contract for this purpose allows me to >> centralize >> >> >> the documentation and behavior of these arguments, get correct blame >> on >> >> >> places where the coercion fails, and abstract the coercion out of >> the code >> >> >> that is using it into its interface. These are all great wins. >> >> >> >> >> >> In my opinion, if I did not use contracts, the only elegant thing to >> do >> >> >> would be to recreate something almost exactly like the contract >> system but >> >> >> called the coercion system. That is absurd to me when contracts >> already do >> >> >> exactly this. >> >> >> >> >> >> Am I just not clever enough to think of another elegant way? >> >> >> Why is there so much resistance to using the contract system in a >> >> >> perfectly legal way according to its own definition & contracts? [2] >> [i.e. >> >> >> "projection" functions are not forced to be projections by any >> means. / >> >> >> contracts already break eq?/equal?-ness / etc] >> >> >> >> >> >> Jay >> >> >> 1. We already have such context-sensitive contracts: >> >> >> >> >> >> >> http://docs.racket-lang.org/xml/index.html#(def._((lib._xml/main..rkt)._permissive/c)) >> >> >> >> >> >> permissive/c exists to allow DrRacket to embed more snips inside the >> >> >> XML boxes, which are otherwise not XML elements. >> >> >> 2. make-contract's projection keyword has the contract (-> any/c >> any/c) >> >> >> >> >> >> The example of make-contract coerces the procedure by restricting >> how >> >> >> many arguments rather than checking that when it is given that >> number of >> >> >> arguments it is used properly, etc. >> >> >> >> >> >> Only flat and chaperone contracts attempt to enforce >> projection-ness. >> >> >> On Sun, Dec 5, 2010 at 9:31 AM, Matthias Felleisen >> >> >> <matth...@ccs.neu.edu> wrote: >> >> >> >> >> >> Jay, coercions aka casts in our world are compound words with -> in >> >> >> between them. Why do you need a new name? >> >> >> >> >> >> (There is an inconsistency in their behavior. To wit >> >> >> >> >> >> Welcome to Racket v5.0.99.4. >> >> >>> (integer->char 1000000000000000) >> >> >> integer->char: expects argument of type <exact integer in >> [0,#x10FFFF], >> >> >> not in [#xD800,#xDFFF]>; given 1000000000000000 >> >> >> >> >> >> === context === >> >> >> /Users/matthias/plt/collects/racket/private/misc.rkt:78:7 >> >> >>> (string->number "a10") >> >> >> #f >> >> >> >> >> >> But that is a historical problem.) >> >> >> >> >> >> ;; --- >> >> >> >> >> >> I am also reluctant to throw contracts at dynamic places. Contract >> >> >> boundaries should be syntactically distinct, e.g., module boundaries >> or >> >> >> define/contract. >> >> >> >> >> >> ;; --- >> >> >> >> >> >> I think you're really just checking an assertion. So perhaps you >> want >> >> >> to go with /a as a suffix. >> >> >> >> >> >> >> >> >> -- Matthias >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> -- >> >> >> Jay McCarthy <j...@cs.byu.edu> >> >> >> Assistant Professor / Brigham Young University >> >> >> http://faculty.cs.byu.edu/~jay >> >> >> >> >> >> "The glory of God is Intelligence" - D&C 93 >> >> >> >> >> >> >> >> >> > >> > >> > >> > -- >> > Jay McCarthy <j...@cs.byu.edu> >> > Assistant Professor / Brigham Young University >> > http://faculty.cs.byu.edu/~jay >> > >> > "The glory of God is Intelligence" - D&C 93 >> > >> > > > > -- > Jay McCarthy <j...@cs.byu.edu> > Assistant Professor / Brigham Young University > http://faculty.cs.byu.edu/~jay > > "The glory of God is Intelligence" - D&C 93 > -- Jay McCarthy <j...@cs.byu.edu> Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay "The glory of God is Intelligence" - D&C 93
_________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev