For that the contract says (output-port? . -> . void) When it should say (output-port? . -> . void?)
On Mar 6, 2015, at 8:16 PM, Matthew Butterick <m...@mbtype.com> wrote: > Curiously, the contract for `response` also requires an (-> output-port? > void?) procedure [1]. The source code agrees. But the examples given in the > docs don't include a (void) return value. Yet they do work. So perhaps > there's a tiny bug where `response` is being more lenient than it's supposed > to be. > > > [1] > http://docs.racket-lang.org/web-server/http.html?q=response#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29 > > > On Fri, Mar 6, 2015 at 4:40 PM, Alexis King <lexi.lam...@gmail.com> wrote: > 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
____________________ Racket Users list: http://lists.racket-lang.org/users