Sorry for the crossed emails. If I understand what's happening correctly,
the code you sent only blames the "deserializing" module because it
shaddows `serialize` and `deserialize` to mean `values`, so the instance is
never actually deserialized or serialized and `deserialize-info:adder-v0`
is never consulted. If I remove the `local` block, the error is displayed
in terms of `+`.
#lang racket
(module server racket
(require racket/serialize)
(provide (contract-out
[adder (-> natural-number/c (-> natural-number/c
natural-number/c))]))
(struct adder (base)
#:property prop:procedure
(λ (this x) (+ (adder-base this) x))
#:property prop:serializable
(make-serialize-info (λ (this) (vector (adder-base this)))
#'deserialize-info:adder-v0
#f
(or (current-load-relative-directory)
(current-directory))))
(define deserialize-info:adder-v0
(make-deserialize-info adder (λ () (error 'adder "can't have cycles"))))
(module+ deserialize-info
(provide deserialize-info:adder-v0)))
(require (submod "." server) racket/serialize)
(define x (serialize (adder 5)))
(displayln x)
(define f (deserialize x))
(f 'not-a-number)
-Philip
On Mon, Jul 24, 2017 at 12:50 PM, Philip McGrath <[email protected]>
wrote:
> It occurs to me that one approach is to use the low-level `contract` form
> directly. It gives better blame than `define/contract`, at least. The
> program:
>
> #lang racket
>
> (module server racket
> (require racket/serialize)
>
> (provide (contract-out
> [adder (-> natural-number/c (-> natural-number/c
> natural-number/c))]))
>
> (struct adder (base)
> #:property prop:procedure
> (λ (this x) (+ (adder-base this) x))
> #:property prop:serializable
> (make-serialize-info (λ (this) (vector (adder-base this)))
> #'deserialize-info:adder-v0
> #f
> (or (current-load-relative-directory)
> (current-directory))))
>
> (define deserialize-info:adder-v0
> (make-deserialize-info
> (λ (base)
> (define inst (adder base))
> (contract (-> natural-number/c natural-number/c)
> inst
> '(definition adder)
> `(deserialization ,inst)
> (object-name adder)
> #f))
> (λ () (error 'adder "can't have cycles"))))
>
> (module+ deserialize-info
> (provide deserialize-info:adder-v0)))
>
> (require (submod "." server) racket/serialize)
>
> ((deserialize (serialize (adder 5))) 'not-a-number)
>
>
> reports the error:
>
> adder: contract violation
> expected: natural-number/c
> given: 'not-a-number
> in: the 1st argument of
> (-> natural-number/c natural-number/c)
> contract from: (definition adder)
> blaming: (deserialization #<procedure:adder>)
> (assuming the contract is correct)
>
>
> -Philip
>
> On Mon, Jul 24, 2017 at 12:35 PM, Philip McGrath <[email protected]
> > wrote:
>
>> That is precisely the contract violation I'd like to see reported, but,
>> without the shadowing of serialize and deserialize, the error is reported
>> in terms of `+`. (And, if it wasn't clear, I do intend to actually read and
>> write the serialized instance.)
>>
>> I (think) I understand why deserialization strips the contract from the
>> instance: the contract is added at the module boundary using the
>> chaperone/impersonator infrastructure, and deserialization uses the
>> unprotected form of `adder` passed to `make-deserialize-info` within the
>> server module.
>>
>> What I don't understand is how to give `make-deserialize-info` a function
>> that (1) has a contract where (2) fulfilling the range part of the contract
>> becomes the deserializing module's obligation — if such a thing is
>> possible. Aside from attempts with `define/contract` (which as I now
>> understand achieved point 1 but not point 2), I've also tried putting the
>> definition of `deserialize-info:adder-v0` in a different module, so that
>> its version of `adder` has a contract, but then the binding isn't seen by
>> `make-serialize-info`.
>>
>> -Philip
>>
>> On Mon, Jul 24, 2017 at 7:30 AM, Matthias Felleisen <[email protected]
>> > wrote:
>>
>>>
>>> On Jul 23, 2017, at 10:50 PM, Philip McGrath <[email protected]>
>>> wrote:
>>>
>>> If I'm following correctly, I think that's what I was trying to do, but
>>> I'm unclear how to give `make-deserialize-info` a variant of
>>> `make-adder` that has a contract. The initial example with
>>> `define/contract` was the closest I've come: it at least reported
>>> violations in terms of `make-adder` rather than `+`, but (as I now
>>> understand) it blamed the `server` module for all violations.
>>>
>>> -Philip
>>>
>>> On Sun, Jul 23, 2017 at 9:27 PM, Matthew Flatt <[email protected]>
>>> wrote:
>>>
>>>> The original example had an explicit deserializer:
>>>>
>>>> At Sun, 23 Jul 2017 19:54:43 -0500, Philip McGrath wrote:
>>>> > (define deserialize-info:adder-v0
>>>> > (make-deserialize-info make-adder
>>>> > (λ () (error 'adder
>>>> > "can't have cycles"))))
>>>>
>>>> You're constructing the deserializer with `make-adder` --- the variant
>>>> from inside the `server` module, so it doesn't have a contract.
>>>>
>>>> I think this is where you want to draw a new boundary by giving
>>>> `make-deserialize-info` a variant of `make-adder` that has a contract.
>>>
>>>
>>>
>>>
>>> Don’t you just want this:
>>>
>>> #lang racket
>>>
>>> (module server racket
>>> (require racket/serialize)
>>>
>>> (provide (contract-out
>>> [adder (-> natural-number/c (-> natural-number/c
>>> natural-number/c))]))
>>>
>>> (struct adder (base)
>>> #:property prop:procedure
>>> (λ (this x) (+ (adder-base this) x))
>>> #:property prop:serializable
>>> (make-serialize-info (λ (this) (vector (adder-base this)))
>>> #'deserialize-info:adder-v0
>>> #f
>>> (or (current-load-relative-directory)
>>> (current-directory))))
>>>
>>> (define deserialize-info:adder-v0
>>> (make-deserialize-info adder (λ () (error 'adder "can't have
>>> cycles"))))
>>>
>>> (module+ deserialize-info
>>> (provide deserialize-info:adder-v0)))
>>>
>>> (require (submod "." server) racket/serialize)
>>>
>>> (local ((define serialize values)
>>> (define deserialize values))
>>> (define x (serialize (adder 5)))
>>> (define f (deserialize x))
>>> (f 'not-a-number))
>>>
>>>
>>>
>>
>
--
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.