The new expression dos not designate an initial field value for x even though the contract says there must be one. You can also specify 'a as the initial value for x inside the class and the contract system won't tell you that your object does not have a correct field value. When you eventually dereference the object you get a contract error. But if you also have (field (y (* x x)) further down, the error message shows again that the init contract isn't checked.
On Jun 6, 2014, at 12:06 PM, Robby Findler <ro...@eecs.northwestern.edu> wrote: > 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