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.

Reply via email to