What is wrong with this? Robby
On Thu, Jun 5, 2014 at 8:13 PM, Matthias Felleisen <matth...@ccs.neu.edu> wrote: > > class/c doesn't check inits properly: > > #lang racket > > (provide > (contract-out > [c% (class/c (init-field [x number?]))])) > > (define c% > (class object% > (field (x 10)) > (super-new))) > > > and now run > > Welcome to Racket v6.0.1.12. >> (require "foo.rkt") >> (new c%) > (object:c% ...) > > > Okay more thinking to do -- Matthias > > > > > On Jun 5, 2014, at 8:49 PM, Roman Klochkov wrote: > > It is maybe closer. > > But inside define-binary-class I also doesn't know the total number of init > arguments. Because library user may give any superclass. And I don't know, > how to get init arguments (or arity for of make-object for a given class) > without calling make-object and reading the error message. > Lake in case > (define base% (class (super-new) (init-field param1 param2))) > (define-binary-class db base% ((a u1) (b u2))) > > Maybe the problem doesn't have a solution. But I see class/c, which has init > and init-fields clauses. Somehow it checks them... > > Thu, 5 Jun 2014 16:36:16 -0400 от Matthias Felleisen <matth...@ccs.neu.edu>: > > > Sorry I am so slow. > > Contracts are first-class values. > > You could modify define-binary-class so that it also creates and defines > a contract P that can be passed along to read-object. Then read-object > can use P like this: > >> #lang racket >> >> (provide >> a% a? >> b% b? >> (contract-out >> (read-object (->i ((c? contract?) (c% any/c)) >> #:rest [l (c?) (lambda (x) (apply c? x))] >> (_ (c%) (is-a?/c c%)))))) >> >> (define a% (class object% [init-field x] (super-new))) >> (define b% (class object% [init-field x y] (super-new))) >> >> (define a? (lambda x (and (= (length x) 1) (andmap number? x)))) >> (define b? (lambda x (and (= (length x) 2) (andmap number? x)))) >> >> (define (read-object __c c% . x) >> (apply make-object c% x)) > > Then you get exactly what you want and pretty precise checking: > >> % !! >> racket >> Welcome to Racket v6.0.1.11. >> > (require "foo.rkt") >> foo.rkt:9:23: is-a/c?: unbound identifier in module >> in: is-a/c? >> context...: >> standard-module-name-resolver >> /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7 >> > (require "foo.rkt") >> foo.rkt:9:31: c%: unbound identifier in module >> in: c% >> context...: >> standard-module-name-resolver >> /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7 >> > (require "foo.rkt") >> > ( read-object b? b% 10 20 ) >> (object:b% ...) >> > ( read-object b? b% 10 ) >> read-object: contract violation >> expected: ...vn/2HtDP/foo.rkt:8:34 >> given: '(10) >> in: the l argument of >> (->i >> ((c? contract?) (c% any/c)) >> #:rest >> (l (c?) (lambda (x) (apply c? x))) >> (_ (c%) (is-a?/c c%))) >> 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 >> arg-checker >> /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7 >> > ( read-object a? a% 10 ) >> (object:a% ...) >> > ( read-object a? a% 10 20) >> read-object: contract violation >> expected: ...vn/2HtDP/foo.rkt:8:34 >> given: '(10 20) >> in: the l argument of >> (->i >> ((c? contract?) (c% any/c)) >> #:rest >> (l (c?) (lambda (x) (apply c? x))) >> (_ (c%) (is-a?/c c%))) >> 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 >> arg-checker >> /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7 > > > > If you want to make sure that a? and a% come together, you can package them > up in structs. > > If you just want to make sure that these contracts come from your binary > class module, you can hide them in applicable structs or something like > that. > > Am I getting closer? -- Matthias > > > > > On Jun 5, 2014, at 4:15 PM, Roman Klochkov <kalimeh...@mail.ru> wrote: > >> 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 >> > >> > >> > >> > >> > > > >> > > > >> > > > -- >> > > > Roman Klochkov >> > > >> > > >> > > >> > > -- >> > > Roman Klochkov >> > >> > >> > >> > -- >> > Roman Klochkov >> >> >> >> -- >> Roman Klochkov > > > > -- > Roman Klochkov > > > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users > ____________________ Racket Users list: http://lists.racket-lang.org/users