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

From: Roman Klochkov (kalimehtar at mail.ru)
Date: Thu Jun 5 21:24:36 EDT 2014

 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 <matthias at 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 < 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
>


-- 
Roman Klochkov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140606/ac27f2cd/attachment-0001.html>

Posted on the users mailing list.