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