[racket] How to get arity of make-object?
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 <matthias at 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 < kalimehtar at 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 < matthias at 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 < kalimehtar at 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 < matthias at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140606/fbdf4fe7/attachment-0001.html>