Ah yes, please forgive my error. I was wrong when I said "the contract for `response` also requires an (-> output-port? void?) procedure". I misread it.
The moral of the story, however, remains the same — contracts are not final because they're infallible; they're infallible because they're final. On Sat, Mar 7, 2015 at 10:23 AM, Jay McCarthy <jay.mccar...@gmail.com> wrote: > Oh and one more thing. The idea of the void? was to help catch > mistakes where someone thought they could return a xexpr or response > structure from these functions and have it returned. > > Jay > > On Sat, Mar 7, 2015 at 1:22 PM, Jay McCarthy <jay.mccar...@gmail.com> > wrote: > > I'm catching up on this thread. > > > > The contracts should all be "void?" and it says "void" then it's > > probably a typo and an error. "void" is a function that takes any > > number of arguments and returns "void", which is not false, so "void" > > is like an "any/c" contract, except that it is less efficient. (The > > contract system will not put the same kind of wrapper when the > > function can return anything.) > > > > I'm loathe to fix this typo though, because I suspect that a lot of > > code relies on the "void" behavior. If anything, I should change it to > > have "any" so that it is more efficient and has the same errors. > > > > Jay > > > > > > On Fri, Mar 6, 2015 at 9:09 PM, André Matheus <amath...@mac.com> wrote: > >> If I understood what Matthew said correctly, the point of the contract > >> requiring void is to prevent > >> an error when someone uses a function returning a string rather than > writing > >> to the output port. > >> > >> But in this case, response should require returning void too, right? > What > >> confused me more than > >> the error message and the contracts was that the same function worked > when > >> creating a response > >> but didn’t work when using response/output, but response/output simply > >> creates a response with > >> default values, so my understanding was that the function should either > work > >> or fail on both. > >> > >> Em 06/03/2015, à(s) 21:40, Alexis King <lexi.lam...@gmail.com> > escreveu: > >> > >> I do sort of agree that the void? requirement is strange and unneeded. > It’s > >> usually only used to indicate that a function provided by some module > >> returns #<void>, but callback functions are usually specified with any > as > >> the return value to allow precisely this sort of thing. > >> > >> On Mar 6, 2015, at 16:26, Matthew Butterick <m...@mbtype.com> wrote: > >> > >>> From the error message, I changed the lambda to return (void) and then > it > >>> worked. > >>> I think maybe the contract is wrong but frankly I don't understand much > >>> about contracts. > >> > >> > >> The contract, by definition, is always right ;) > >> > >> In this case, `response/output` takes as its first argument a procedure > that > >> accepts an output-port and returns void. [1] In contract-speak this is > >> commonly written with dot notation as: > >> > >> (output-port? . -> . void?) > >> > >> but it appears in error messages, like the one above, with the > equivalent > >> notation: > >> > >> (-> output-port? void?) > >> > >> Note also that the error says the contract violation was "in the range > of > >> the 1st argument of" ... [giant contract follows]. That helps track > down the > >> error. The contract for the first argument is '(-> output-port? void?)'. > >> This is a procedure contract. And "the range of" a procedure contract > means > >> the contract on the return value. Which in this case is `void?`. So the > >> complaint is that the procedure given in the first argument is returning > >> '11' when it should be returning void. > >> > >> Why is (-> output-port? void?) the contract for the first arg of > >> `response/output`? The idea is that you write to the output-port > directly > >> rather than returning a value to the caller. Insisting on void as a > return > >> value imposes an extra measure of discipline, and sets an expectation. > >> > >> The reason your 'not-working' dispatcher is not working is that > >> `write-bytes` does two things: it sends bytes to the output port, but > then > >> also returns the number of bytes written. [2] So this procedure: > >> > >> (λ (op) (write-bytes #"Hello world" op)) > >> > >> is defective because it returns the number of bytes. Meaning, it breaks > the > >> contract, which demands void. (That's also why your error is '11': > that's > >> the number of bytes in "Hello world"). > >> > >> But your revised procedure: > >> > >> (λ (op) (write-bytes #"Hello world" op) (void)) > >> > >> Meets the contract because it ignores the return value from > `write-bytes` > >> and returns (void) instead. > >> > >> You should repeat this technique whenever you use `response/output`. > >> > >> You can also look into `response/full` and `response/xexpr`, which can > be a > >> more convenient way of making simple HTML or text responses. > >> > >> > >> > >> [1] > >> > http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29 > >> > >> which cross-references > >> > >> > http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29 > >> > >> [2] > >> > http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29 > >> > >> which cross-references > >> > >> > http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29 > >> > >> > >> > >> On Fri, Mar 6, 2015 at 3:48 PM, André Matheus <amath...@mac.com> wrote: > >>> > >>> Hi, starting a project of mine, I've setup a dispatch rule and a > function > >>> to return the response. > >>> To make things simple, I've used response/output, with a lambda > writing to > >>> the output-port. > >>> However, I've got the error: > >>> > >>> response/output: contract violation > >>> expected: void? > >>> given: 11 > >>> in: the range of > >>> the 1st argument of > >>> (->* > >>> ((-> output-port? void?)) > >>> (#:code > >>> number? > >>> #:headers > >>> (listof header?) > >>> #:message > >>> bytes? > >>> #:mime-type > >>> (or/c bytes? #f) > >>> #:seconds > >>> number?) > >>> response?) > >>> contract from: > >>> <pkgs>/web-server-lib/web-server/http/response-structs.rkt > >>> blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt > >>> (assuming the contract is correct) > >>> at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2 > >>> context...: > >>> /usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: > >>> raise-blame-error16 > >>> > >>> > /usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12 > >>> > >>> So I've tried to use a response, with the same lambda, and it worked. > >>> From the error message, I changed the lambda to return (void) and then > it > >>> worked. > >>> > >>> I think maybe the contract is wrong but frankly I don't understand much > >>> about contracts. > >>> > >>> I've setup some code that exposes the problem. Navigating to "/working" > >>> and "/fixed" works > >>> fine; navigating to "/not-working" exposes the problem. > >>> > >>> #lang racket > >>> (require web-server/dispatch > >>> web-server/servlet-env > >>> net/url > >>> web-server/http/request-structs > >>> web-server/http/response-structs) > >>> > >>> (define (not-working req) > >>> (response/output (λ (op) (write-bytes #"Hello world" op)))) > >>> > >>> (define (working req) > >>> (response > >>> 301 #"OK" > >>> (current-seconds) TEXT/HTML-MIME-TYPE > >>> empty > >>> (λ (op) (write-bytes #"Hello world" op)))) > >>> > >>> (define (fixed req) > >>> (response/output (λ (op) (write-bytes #"Hello world" op) (void)))) > >>> > >>> (define (url->request u) > >>> (make-request #"GET" (string->url u) empty > >>> (delay empty) #f "1.2.3.4" 80 "4.3.2.1")) > >>> > >>> (define-values (agenda-dispatch agenda-url) > >>> (dispatch-rules > >>> [("working") working] > >>> [("not-working") not-working] > >>> [("fixed") fixed])) > >>> > >>> (define (main) > >>> (serve/servlet agenda-dispatch > >>> #:servlet-regexp #rx"" > >>> #:servlet-path "")) > >>> > >>> (module+ main > >>> (main)) > >>> > >>> The contracts in response-structs.rkt: > >>> > >>> (provide/contract > >>> [struct response > >>> ([code number?] > >>> [message bytes?] > >>> [seconds number?] > >>> [mime (or/c false/c bytes?)] > >>> [headers (listof header?)] > >>> [output (output-port? . -> . void)])] > >>> [response/full (-> number? bytes? number? (or/c false/c bytes?) > (listof > >>> header?) (listof bytes?) response?)] > >>> [response/output (->* ((-> output-port? void?)) > >>> (#:code number? > >>> #:message bytes? > >>> #:seconds number? > >>> #:mime-type (or/c bytes? #f) > >>> #:headers (listof header?)) > >>> response?)] > >>> [TEXT/HTML-MIME-TYPE bytes?]) > >>> > >>> Is the contract wrong or am I doing something weird? > >>> > >>> Thanks, > >>> > >>> André > >>> > >>> ____________________ > >>> Racket Users list: > >>> http://lists.racket-lang.org/users > >>> > >> > >> ____________________ > >> Racket Users list: > >> http://lists.racket-lang.org/users > >> > >> > >> > >> > >> ____________________ > >> Racket Users list: > >> http://lists.racket-lang.org/users > >> > > > > > > > > -- > > Jay McCarthy > > http://jeapostrophe.github.io > > > > "Wherefore, be not weary in well-doing, > > for ye are laying the foundation of a great work. > > And out of small things proceedeth that which is great." > > - D&C 64:33 > > > > -- > Jay McCarthy > http://jeapostrophe.github.io > > "Wherefore, be not weary in well-doing, > for ye are laying the foundation of a great work. > And out of small things proceedeth that which is great." > - D&C 64:33 >
____________________ Racket Users list: http://lists.racket-lang.org/users