Can't you use is-a?/c like this: 

> #lang racket
> 
> (provide
>   a%
>   b%
>   (contract-out
>     (read-object (case->
>                  [-> (is-a?/c a%) number? number?]
>                  [-> (is-a?/c b%) number? number? number?]))))
> 
> (define a% (class object% (super-new)))
> (define b% (class object% (super-new)))
> 
> (define read-object
>   (case-lambda
>     [(a x) x]
>     [(b x y) (+ x y)]))


and use this module like this: 

> % racket
> Welcome to Racket v6.0.1.11.
> > (require "foo.rkt")
> > (read-object (new a%) 10)
> 10
> > (read-object (new a%) 10 20)
> read-object: contract violation
>   expected: (is-a?/c b%)
>   given: (object:a% ...)
>   in: the domain of
>       the 2nd case of
>       (case->
>        (-> (is-a?/c a%) number? number?)
>        (-> (is-a?/c b%) number? number? number?))
>   contract from: 
>       /Users/matthias/svn/2HtDP/foo.rkt
>   blaming: top-level
>   at: /Users/matthias/svn/2HtDP/foo.rkt:7.5
>   context...:
>    
> /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: 
> raise-blame-error16
>    /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7
> > (read-object (new b%) 10 20)
> 30
> > (read-object (new b%) 10)
> read-object: contract violation
>   expected: (is-a?/c a%)
>   given: (object:b% ...)
>   in: the domain of
>       the 1st case of
>       (case->
>        (-> (is-a?/c a%) number? number?)
>        (-> (is-a?/c b%) number? number? number?))
>   contract from: 
>       /Users/matthias/svn/2HtDP/foo.rkt
>   blaming: top-level
>   at: /Users/matthias/svn/2HtDP/foo.rkt:7.5
>   context...:
>    
> /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: 
> raise-blame-error16
>    /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7



On Jun 5, 2014, at 3:19 PM, Roman Klochkov <kalimeh...@mail.ru> wrote:

> (define (read-object binary-class in . args)
>   (send (apply make-object binary-class args) read in))
> 
> read-object takes a class as a first arg, and additional arguments to make an 
> object of that class.
> 
> I can't make case-> because I don't know j,ject of what (user-defined) class 
> will be created with the function by user of my library.
> 
> This case is described in Racket Guide 7,3.9 
> http://docs.racket-lang.org/guide/contracts-general-functions.html#%28part._contracts-no-domain%29
>  , where recommended to use unconstrained-domain-> with 
> procedure-arity-includes? , but it doesnt' work with make-object
> 
> Thu, 5 Jun 2014 14:51:21 -0400 от Matthias Felleisen <matth...@ccs.neu.edu>:
> 
> From what I understand now, you want a contract for a function that creates 
> objects from a variable number of arguments. If you write your module 
> interface like this, 
> 
> > #lang racket
> > 
> > (provide
> > (contract-out
> > (read-object (case->
> > [-> 'a number? number?]
> > [-> 'b number? number? number?]))))
> > 
> > (define read-object
> > (case-lambda
> > [(a x) x]
> > [(b x y) (+ x y)]))
> 
> you can get checked variable-arity behavior: 
> 
> > Welcome to Racket v6.0.1.11.
> > > (require "foo.rkt")
> > > (read-object 'a 10)
> > 10
> > > (read-object 'b 10 20)
> > 30
> > > (read-object 'b 10)
> > read-object: contract violation
> > expected: (quote a)
> > given: 'b
> > in: the domain of
> > the 1st case of
> > (case->
> > (-> 'a number? number?)
> > (-> 'b number? number? number?))
> > contract from: 
> > /Users/matthias/svn/2HtDP/foo.rkt
> > blaming: top-level
> > at: /Users/matthias/svn/2HtDP/foo.rkt:5.5
> > context...:
> > /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0:
> >  raise-blame-error16
> > /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7
> > > (read-object 'a 10 20)
> > read-object: contract violation
> > expected: (quote b)
> > given: 'a
> > in: the domain of
> > the 2nd case of
> > (case->
> > (-> 'a number? number?)
> > (-> 'b number? number? number?))
> > contract from: 
> > /Users/matthias/svn/2HtDP/foo.rkt
> > blaming: top-level
> > at: /Users/matthias/svn/2HtDP/foo.rkt:5.5
> > context...:
> > /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0:
> >  raise-blame-error16
> > /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7
> 
> 
> I think you can use ->i contracts inside of the case-> clauses if you need 
> more precision. 
> 
> If I am still misunderstanding your question, sorry. 
> 
> -- Matthias
> 
> 
>  
> 
> 
> On Jun 5, 2014, at 1:41 PM, Roman Klochkov <kalimeh...@mail.ru> wrote:
> 
> > It is not writing, but reading. I'm making uinversal library for binary 
> > data (like dbf, mp3 id3 tags, and so on) mapping to objects
> > https://github.com/Kalimehtar/binary-class
> > 
> > read-object simply
> > 
> > (define (read-object binary-class in . args)
> > (send (apply make-object binary-class args) read in))
> > 
> > But I don't like, that contract may not give correct error message for 
> > wrong nomber of items in args.
> > 
> > 
> > Thu, 5 Jun 2014 12:31:49 -0400 от Matthias Felleisen <matth...@ccs.neu.edu>:
> > 
> > Do you control the writing of objects to a port? If so, check out 
> > 'serialization.' If not, I don't think I can help you. Sorry -- Matthias
> > 
> > 
> > 
> > On Jun 5, 2014, at 12:29 PM, Roman Klochkov <kalimeh...@mail.ru> wrote:
> > 
> > > I don't control class creation.
> > > I need to make a wrapper around make-object and attach contract to the 
> > > wrapper.
> > > 
> > > Now I have
> > > (provide/contract
> > > [read-object (->i ([binary-class (implementation?/c binary<%>)]
> > > [port input-port?])
> > > #:rest [args list?]
> > > [result (binary-class) (is-a?/c binary-class)])])
> > > 
> > > I cannot control number of args. Now, when error encountered I have 
> > > confusing error message mentioning "instantiate".
> > > 
> > > Thu, 5 Jun 2014 12:13:26 -0400 от Matthias Felleisen 
> > > <matth...@ccs.neu.edu>:
> > > 
> > > Here is the pattern I recommend: 
> > > 
> > > Welcome to Racket v6.0.1.11.
> > > > (define (create-c #:x [x 0]) (new c% [x x]))
> > > > (define c% (class object% (init-field x) (super-new)))
> > > 
> > > That is, a class comes with a 'factory' definition, a function that 
> > > creates instances and uses keywords similar to those used by the class 
> > > initializer. If you then export these factories, you can enforce 
> > > invariants and also probe the factory for the information you want: 
> > > 
> > > > (create-c)
> > > (object:c% ...)
> > > > (create-c #:x 10)
> > > (object:c% ...)
> > > > (procedure-arity create-c)
> > > 0
> > > > (procedure-keywords create-c)
> > > '()
> > > '(#:x)
> > > 
> > > 
> > > Yes, one could argue that this is a poor man's substitute for missing 
> > > class reflection. -- Matthias
> > > 
> > > 
> > > 
> > > 
> > > 
> > > 
> > > On Jun 5, 2014, at 11:32 AM, Roman Klochkov <kalimeh...@mail.ru> wrote:
> > > 
> > > > For any procedure I can use procedure-arity. But how to get the number 
> > > > of init arguments for a class?
> > > > 
> > > > Or maybe there are any other way to make a contract, like in Guide 
> > > > 7.3.9, where one can compare number of arguments and arity of the 
> > > > function, but when using (make-object someclass ...)
> > > > instead of the function.
> > > > 
> > > > 
> > > > -- 
> > > > Roman Klochkov
> > > > ____________________
> > > > Racket Users list:
> > > > http://lists.racket-lang.org/users
> > > 
> > > 
> > > 
> > > -- 
> > > Roman Klochkov
> > 
> > 
> > 
> > -- 
> > Roman Klochkov
> 
> 
> 
> -- 
> Roman Klochkov


____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to