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