<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">If I understood what Matthew said correctly, the point of the contract requiring void is to prevent<div class="">an error when someone uses a function returning a string rather than writing to the output port.</div><div class=""><br class=""></div><div class="">But in this case, response should require returning void too, right? What confused me more than</div><div class="">the error message and the contracts was that the same function worked when creating a response</div><div class="">but didn’t work when using response/output, but response/output simply creates a response with</div><div class="">default values, so my understanding was that the function should either work or fail on both.<br class=""><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Em 06/03/2015, à(s) 21:40, Alexis King <<a href="mailto:lexi.lambda@gmail.com" class="">lexi.lambda@gmail.com</a>> escreveu:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I do sort of agree that the <font face="Courier" class="">void?</font> requirement is strange and unneeded. It’s usually only used to indicate that a function provided by some module returns <font face="Courier" class="">#<void></font>, but callback functions are usually specified with <font face="Courier" class="">any</font> as the return value to allow precisely this sort of thing.</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 6, 2015, at 16:26, Matthew Butterick <<a href="mailto:mb@mbtype.com" class="">mb@mbtype.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.8000001907349px" class="">From the error message, I changed the lambda to return (void) and then it worked.</span><br style="font-size:12.8000001907349px" class=""><span style="font-size:12.8000001907349px" class="">I think maybe the contract is wrong but frankly I don't understand much about contracts.</span></blockquote><div class=""><br class=""></div><div class="">The contract, by definition, is always right ;)</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class="">(output-port? . -> . void?) </div><div class=""><br class=""></div><div class="">but it appears in error messages, like the one above, with the equivalent notation:</div><div class=""><br class=""></div><div class="">(-> output-port? void?)<br class=""></div><div class=""><br class=""></div><div class=""><div class="">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.</div></div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><span style="font-size:12.8000001907349px" class="">(λ (op) (write-bytes #"Hello world" op))</span><br class=""></div><div class=""><span style="font-size:12.8000001907349px" class=""><br class=""></span></div><div class=""><span style="font-size:12.8000001907349px" class="">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"). </span></div><div class=""><span style="font-size:12.8000001907349px" class=""><br class=""></span></div><div class=""><span style="font-size:12.8000001907349px" class="">But your revised procedure:</span></div><div class=""><span style="font-size:12.8000001907349px" class=""><br class=""></span></div><div class=""><span style="font-size:12.8000001907349px" class="">(λ (op) (write-bytes #"Hello world" op) (void))</span><span style="font-size:12.8000001907349px" class=""><br class=""></span></div><div class=""><span style="font-size:12.8000001907349px" class=""><br class=""></span></div><div class=""><span style="font-size:12.8000001907349px" class="">Meets the contract because it ignores the return value from `write-bytes` and returns (void) instead.</span></div><div class=""><br class=""></div><div class="">You should repeat this technique whenever you use `response/output`.</div><div class=""><br class=""></div><div class="">You can also look into `response/full` and `response/xexpr`, which can be a more convenient way of making simple HTML or text responses.</div><div class=""><br class=""></div><div class=""><span style="font-size:12.8000001907349px" class=""><br class=""></span></div><div class=""><br class=""></div><div class="">[1] <a href="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" class="">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</a></div><div class=""><br class=""></div><div class="">which cross-references</div><div class=""><br class=""></div><div class=""><a href="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" class="">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</a><br class=""></div><div class=""><br class=""></div><div class="">[2] <a href="http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29" class="">http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29</a></div><div class=""><br class=""></div><div class="">which cross-references</div><div class=""><br class=""></div><div class=""><a href="http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29" class="">http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29</a><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Fri, Mar 6, 2015 at 3:48 PM, André Matheus <span dir="ltr" class=""><<a href="mailto:amatheus@mac.com" target="_blank" class="">amatheus@mac.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class=""><div class="">Hi, starting a project of mine, I've setup a dispatch rule and a function to return the response.<br class="">To make things simple, I've used response/output, with a lambda writing to the output-port.<br class="">However, I've got the error:<br class=""><br class=""><span style="font-size:12px" class="">response/output: contract violation</span><br class=""><span style="font-size:12px" class=""> expected: void?</span><br class=""><span style="font-size:12px" class=""> given: 11</span><br class=""><span style="font-size:12px" class=""> in: the range of</span><br class=""><span style="font-size:12px" class=""> the 1st argument of</span><br class=""><span style="font-size:12px" class=""> (->*</span><br class=""><span style="font-size:12px" class=""> ((-> output-port? void?))</span><br class=""><span style="font-size:12px" class=""> (#:code</span><br class=""><span style="font-size:12px" class=""> number?</span><br class=""><span style="font-size:12px" class=""> #:headers</span><br class=""><span style="font-size:12px" class=""> (listof header?)</span><br class=""><span style="font-size:12px" class=""> #:message</span><br class=""><span style="font-size:12px" class=""> bytes?</span><br class=""><span style="font-size:12px" class=""> #:mime-type</span><br class=""><span style="font-size:12px" class=""> (or/c bytes? #f)</span><br class=""><span style="font-size:12px" class=""> #:seconds</span><br class=""><span style="font-size:12px" class=""> number?)</span><br class=""><span style="font-size:12px" class=""> response?)</span><br class=""><span style="font-size:12px" class=""> contract from: </span><br class=""><span style="font-size:12px" class=""> <pkgs>/web-server-lib/web-server/http/response-structs.rkt</span><br class=""><span style="font-size:12px" class=""> blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt</span><br class=""><span style="font-size:12px" class=""> (assuming the contract is correct)</span><br class=""><span style="font-size:12px" class=""> at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2</span><br class=""><span style="font-size:12px" class=""> context...:</span><br class=""><span style="font-size:12px" class=""> /usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16</span><br class=""><span style="font-size:12px" class=""> /usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12</span><br class=""><br class="">So I've tried to use a response, with the same lambda, and it worked.<br class="">From the error message, I changed the lambda to return (void) and then it worked.<br class=""><br class="">I think maybe the contract is wrong but frankly I don't understand much about contracts.<br class=""><br class="">I've setup some code that exposes the problem. Navigating to "/working" and "/fixed" works<br class="">fine; navigating to "/not-working" exposes the problem.<br class=""><br class="">#lang racket<br class="">(require web-server/dispatch<br class=""> web-server/servlet-env<br class=""> net/url<br class=""> web-server/http/request-structs<br class=""> web-server/http/response-structs)<br class=""><br class="">(define (not-working req)<br class=""> (response/output (λ (op) (write-bytes #"Hello world" op))))<br class=""><br class="">(define (working req)<br class=""> (response<br class=""> 301 #"OK"<br class=""> (current-seconds) TEXT/HTML-MIME-TYPE<br class=""> empty<br class=""> (λ (op) (write-bytes #"Hello world" op))))<br class=""><br class="">(define (fixed req)<br class=""> (response/output (λ (op) (write-bytes #"Hello world" op) (void))))<br class=""><br class="">(define (url->request u)<br class=""> (make-request #"GET" (string->url u) empty<br class=""> (delay empty) #f "1.2.3.4" 80 "4.3.2.1"))<br class=""><br class="">(define-values (agenda-dispatch agenda-url)<br class=""> (dispatch-rules<br class=""> [("working") working]<br class=""> [("not-working") not-working]<br class=""> [("fixed") fixed]))<br class=""><br class="">(define (main)<br class=""> (serve/servlet agenda-dispatch<br class=""> #:servlet-regexp #rx""<br class=""> #:servlet-path ""))<br class=""><br class="">(module+ main<br class=""> (main))<br class=""><br class="">The contracts in response-structs.rkt:<br class=""><br class="">(provide/contract<br class=""> [struct response<br class=""> ([code number?]<br class=""> [message bytes?]<br class=""> [seconds number?]<br class=""> [mime (or/c false/c bytes?)]<br class=""> [headers (listof header?)]<br class=""> [output (output-port? . -> . void)])]<br class=""> [response/full (-> number? bytes? number? (or/c false/c bytes?) (listof header?) (listof bytes?) response?)]<br class=""> [response/output (->* ((-> output-port? void?))<br class=""> (#:code number?<br class=""> #:message bytes?<br class=""> #:seconds number?<br class=""> #:mime-type (or/c bytes? #f)<br class=""> #:headers (listof header?))<br class=""> response?)]<br class=""> [TEXT/HTML-MIME-TYPE bytes?])<br class=""><br class="">Is the contract wrong or am I doing something weird?<br class=""><br class="">Thanks,<br class=""><br class="">André<br class=""></div></div><br class="">____________________<br class="">
Racket Users list:<br class="">
<a href="http://lists.racket-lang.org/users" target="_blank" class="">http://lists.racket-lang.org/users</a><br class="">
<br class=""></blockquote></div><br class=""></div></div>
____________________<br class=""> Racket Users list:<br class=""> <a href="http://lists.racket-lang.org/users" class="">http://lists.racket-lang.org/users</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></body></html>