I don't create classes. I provide a function read-object, so user can do (require binary-class) (define base% (class (super-new) (init-field param1 param2))) (define-binary-class db base% ((a u1) (b u2)))
(define data (read-object db my-file data-param1 data-param2) And I try to make a contract, so when he made an error in last call and wrote (define data (read-object db my-file data-param1)), then error message whould blame read-object, not `instantiate' Thu, 5 Jun 2014 16:08:39 -0400 от Matthias Felleisen <matth...@ccs.neu.edu>: > >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 > -- Roman Klochkov
____________________ Racket Users list: http://lists.racket-lang.org/users