Sorry for being so late to the discussion, but I agree that something like `class-constructor-arity` and `class-constructor-arity-includes?` should be added to `racket/class`.
At Fri, 06 Jun 2014 05:24:36 +0400, Roman Klochkov wrote: > Hm... But reading it's sources give me some clues. > > Now I have working dirty hack > > #lang racket/base > (require racket/private/class-internal) > > (define (class-inits cls) > (apply append > (for/list ([c (in-vector (class-supers cls))]) > (class-init-args c)))) > > It gives the list of class init arguments. Maybe someone also needs it. > Thu, 5 Jun 2014 21:13:47 -0400 от Matthias Felleisen <matth...@ccs.neu.edu>: > > > >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._cont > racts-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 > > > > > -- > Roman Klochkov > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users