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