[racket] How to get arity of make-object?

From: Roman Klochkov (kalimehtar at mail.ru)
Date: Thu Jun 5 20:49:02 EDT 2014

 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>

Posted on the users mailing list.