<html><head><base href="https://e.mail.ru/"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div>class/c doesn't check inits properly: </div><div><br></div><div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">#lang racket</font></div><div><font class="Apple-style-span" color="#000000"><br></font></div><div><font class="Apple-style-span" color="#000000">(provide</font></div><div><font class="Apple-style-span" color="#000000">  (contract-out</font></div><div><font class="Apple-style-span" color="#000000">    [c% (class/c (init-field [x number?]))]))</font></div><div><font class="Apple-style-span" color="#000000"><br></font></div><div><font class="Apple-style-span" color="#000000">(define c%</font></div><div><font class="Apple-style-span" color="#000000">  (class object%</font></div><div><font class="Apple-style-span" color="#000000">    (field (x 10))</font></div><div><font class="Apple-style-span" color="#000000">    (super-new)))</font></div></blockquote></div><div><div><br></div></div><div>and now run</div><div><br></div><div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">Welcome to Racket v6.0.1.12.</font></div><div><font class="Apple-style-span" color="#000000">> (require "foo.rkt")</font></div><div><font class="Apple-style-span" color="#000000">> (new c%)</font></div><div><font class="Apple-style-span" color="#000000">(object:c% ...)</font></div></blockquote><br></div><div>Okay more thinking to do -- Matthias</div><div><br></div><div><br></div><div><br></div><br><div><div>On Jun 5, 2014, at 8:49 PM, Roman Klochkov wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">
<div>It is maybe closer.<br><br>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.<br>Lake in case<br>(define base% (class (super-new) (init-field param1 param2)))<br>(define-binary-class db base% ((a u1) (b u2)))<br><br>Maybe the problem doesn't have a solution. But I see class/c, which has init and init-fields clauses. Somehow it checks them...<br><br>Thu, 5 Jun 2014 16:36:16 -0400 от Matthias Felleisen <<a href="mailto:matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>>:<br>
<blockquote style="border-left:1px solid #0857A6; margin:10px; padding:0 0 0 10px;">
        <div id="">
        



    









        
        


        
        
        
        
        

        
        

        
        



<div class="js-helper js-readmsg-msg">
        <style type="text/css"></style>
        <div>
                <base target="_self" href="https://e.mail.ru/">
                
                        <div id="style_14020005770000000444_BODY"><br>
Sorry I am so slow. <br>
<br>
Contracts are first-class values. <br>
<br>
You could modify define-binary-class so that it also creates and defines<br>
a contract P that can be passed along to read-object. Then read-object<br>
can use P like this: <br>
<br>
> #lang racket<br>
> <br>
> (provide<br>
>   a% a?<br>
>   b% b?<br>
>   (contract-out<br>
>     (read-object (->i ((c? contract?) (c% any/c))<br>
>               #:rest [l (c?) (lambda (x) (apply c? x))]<br>
>               (_ (c%) (is-a?/c c%))))))<br>
> <br>
> (define a% (class object% [init-field x] (super-new)))<br>
> (define b% (class object% [init-field x y] (super-new)))<br>
> <br>
> (define a? (lambda x (and (= (length x) 1) (andmap number? x))))<br>
> (define b? (lambda x (and (= (length x) 2) (andmap number? x))))<br>
> <br>
> (define (read-object __c c% . x)<br>
>   (apply make-object c% x))<br>
<br>
Then you get exactly what you want and pretty precise checking: <br>
<br>
> % !!<br>
> racket<br>
> Welcome to Racket v6.0.1.11.<br>
> > (require "foo.rkt")<br>
> foo.rkt:9:23: is-a/c?: unbound identifier in module<br>
>   in: is-a/c?<br>
>   context...:<br>
>    standard-module-name-resolver<br>
>    /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> > (require "foo.rkt")<br>
> foo.rkt:9:31: c%: unbound identifier in module<br>
>   in: c%<br>
>   context...:<br>
>    standard-module-name-resolver<br>
>    /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> > (require "foo.rkt")<br>
> > ( read-object b? b% 10 20 )<br>
> (object:b% ...)<br>
> > ( read-object b? b% 10 )<br>
> read-object: contract violation<br>
>   expected: ...vn/2HtDP/foo.rkt:8:34<br>
>   given: '(10)<br>
>   in: the l argument of<br>
>       (->i<br>
>        ((c? contract?) (c% any/c))<br>
>        #:rest<br>
>        (l (c?) (lambda (x) (apply c? x)))<br>
>        (_ (c%) (is-a?/c c%)))<br>
>   contract from: <br>
>       /Users/matthias/svn/2HtDP/foo.rkt<br>
>   blaming: top-level<br>
>   at: /Users/matthias/svn/2HtDP/foo.rkt:7.5<br>
>   context...:<br>
>    /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16<br>
>    arg-checker<br>
>    /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> > ( read-object a? a% 10 )<br>
> (object:a% ...)<br>
> > ( read-object a? a% 10 20)<br>
> read-object: contract violation<br>
>   expected: ...vn/2HtDP/foo.rkt:8:34<br>
>   given: '(10 20)<br>
>   in: the l argument of<br>
>       (->i<br>
>        ((c? contract?) (c% any/c))<br>
>        #:rest<br>
>        (l (c?) (lambda (x) (apply c? x)))<br>
>        (_ (c%) (is-a?/c c%)))<br>
>   contract from: <br>
>       /Users/matthias/svn/2HtDP/foo.rkt<br>
>   blaming: top-level<br>
>   at: /Users/matthias/svn/2HtDP/foo.rkt:7.5<br>
>   context...:<br>
>    /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16<br>
>    arg-checker<br>
>    /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
<br>
<br>
<br>
If you want to make sure that a? and a% come together, you can package them up in structs. <br>
<br>
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. <br>
<br>
Am I getting closer? -- Matthias<br>
<br>
<br>
<br>
<br>
On Jun 5, 2014, at 4:15 PM, Roman Klochkov <<a href="x-msg://63/compose?To=kalimehtar@mail.ru">kalimehtar@mail.ru</a>> wrote:<br>
<br>
> I don't create classes. I provide a function read-object, so user can do<br>
> <br>
> (require binary-class)<br>
> (define base% (class (super-new) (init-field param1 param2)))<br>
> (define-binary-class db base% ((a u1) (b u2)))<br>
> <br>
> (define data (read-object db my-file data-param1 data-param2)<br>
> <br>
> And I try to make a contract, so when he made an error in last call and wrote<br>
> <br>
> (define data (read-object db my-file data-param1)), then error message whould blame read-object, not `instantiate'<br>
> <br>
> Thu, 5 Jun 2014 16:08:39 -0400 от Matthias Felleisen <<a href="x-msg://63/compose?To=matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>>:<br>
> <br>
> Can't you use is-a?/c like this: <br>
> <br>
> > #lang racket<br>
> > <br>
> > (provide<br>
> > a%<br>
> > b%<br>
> > (contract-out<br>
> > (read-object (case-><br>
> > [-> (is-a?/c a%) number? number?]<br>
> > [-> (is-a?/c b%) number? number? number?]))))<br>
> > <br>
> > (define a% (class object% (super-new)))<br>
> > (define b% (class object% (super-new)))<br>
> > <br>
> > (define read-object<br>
> > (case-lambda<br>
> > [(a x) x]<br>
> > [(b x y) (+ x y)]))<br>
> <br>
> <br>
> and use this module like this: <br>
> <br>
> > % racket<br>
> > Welcome to Racket v6.0.1.11.<br>
> > > (require "foo.rkt")<br>
> > > (read-object (new a%) 10)<br>
> > 10<br>
> > > (read-object (new a%) 10 20)<br>
> > read-object: contract violation<br>
> > expected: (is-a?/c b%)<br>
> > given: (object:a% ...)<br>
> > in: the domain of<br>
> > the 2nd case of<br>
> > (case-><br>
> > (-> (is-a?/c a%) number? number?)<br>
> > (-> (is-a?/c b%) number? number? number?))<br>
> > contract from: <br>
> > /Users/matthias/svn/2HtDP/foo.rkt<br>
> > blaming: top-level<br>
> > at: /Users/matthias/svn/2HtDP/foo.rkt:7.5<br>
> > context...:<br>
> > /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16<br>
> > /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> > > (read-object (new b%) 10 20)<br>
> > 30<br>
> > > (read-object (new b%) 10)<br>
> > read-object: contract violation<br>
> > expected: (is-a?/c a%)<br>
> > given: (object:b% ...)<br>
> > in: the domain of<br>
> > the 1st case of<br>
> > (case-><br>
> > (-> (is-a?/c a%) number? number?)<br>
> > (-> (is-a?/c b%) number? number? number?))<br>
> > contract from: <br>
> > /Users/matthias/svn/2HtDP/foo.rkt<br>
> > blaming: top-level<br>
> > at: /Users/matthias/svn/2HtDP/foo.rkt:7.5<br>
> > context...:<br>
> > /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16<br>
> > /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> <br>
> <br>
> <br>
> On Jun 5, 2014, at 3:19 PM, Roman Klochkov <<a href="x-msg://63/compose?To=kalimehtar@mail.ru">kalimehtar@mail.ru</a>> wrote:<br>
> <br>
> > (define (read-object binary-class in . args)<br>
> > (send (apply make-object binary-class args) read in))<br>
> > <br>
> > read-object takes a class as a first arg, and additional arguments to make an object of that class.<br>
> > <br>
> > 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.<br>
> > <br>
> > This case is described in Racket Guide 7,3.9 <a href="http://docs.racket-lang.org/guide/contracts-general-functions.html#%28part._contracts-no-domain%29" target="_blank">http://docs.racket-lang.org/guide/contracts-general-functions.html#%28part._contracts-no-domain%29</a> , where recommended to use unconstrained-domain-> with procedure-arity-includes? , but it doesnt' work with make-object<br>
> > <br>
> > Thu, 5 Jun 2014 14:51:21 -0400 от Matthias Felleisen <<a href="x-msg://63/compose?To=matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>>:<br>
> > <br>
> > 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, <br>
> > <br>
> > > #lang racket<br>
> > > <br>
> > > (provide<br>
> > > (contract-out<br>
> > > (read-object (case-><br>
> > > [-> 'a number? number?]<br>
> > > [-> 'b number? number? number?]))))<br>
> > > <br>
> > > (define read-object<br>
> > > (case-lambda<br>
> > > [(a x) x]<br>
> > > [(b x y) (+ x y)]))<br>
> > <br>
> > you can get checked variable-arity behavior: <br>
> > <br>
> > > Welcome to Racket v6.0.1.11.<br>
> > > > (require "foo.rkt")<br>
> > > > (read-object 'a 10)<br>
> > > 10<br>
> > > > (read-object 'b 10 20)<br>
> > > 30<br>
> > > > (read-object 'b 10)<br>
> > > read-object: contract violation<br>
> > > expected: (quote a)<br>
> > > given: 'b<br>
> > > in: the domain of<br>
> > > the 1st case of<br>
> > > (case-><br>
> > > (-> 'a number? number?)<br>
> > > (-> 'b number? number? number?))<br>
> > > contract from: <br>
> > > /Users/matthias/svn/2HtDP/foo.rkt<br>
> > > blaming: top-level<br>
> > > at: /Users/matthias/svn/2HtDP/foo.rkt:5.5<br>
> > > context...:<br>
> > > /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16<br>
> > > /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> > > > (read-object 'a 10 20)<br>
> > > read-object: contract violation<br>
> > > expected: (quote b)<br>
> > > given: 'a<br>
> > > in: the domain of<br>
> > > the 2nd case of<br>
> > > (case-><br>
> > > (-> 'a number? number?)<br>
> > > (-> 'b number? number? number?))<br>
> > > contract from: <br>
> > > /Users/matthias/svn/2HtDP/foo.rkt<br>
> > > blaming: top-level<br>
> > > at: /Users/matthias/svn/2HtDP/foo.rkt:5.5<br>
> > > context...:<br>
> > > /Users/matthias/plt/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16<br>
> > > /Users/matthias/plt/racket/collects/racket/private/misc.rkt:87:7<br>
> > <br>
> > <br>
> > I think you can use ->i contracts inside of the case-> clauses if you need more precision. <br>
> > <br>
> > If I am still misunderstanding your question, sorry. <br>
> > <br>
> > -- Matthias<br>
> > <br>
> > <br>
> > <br>
> > <br>
> > > > <br>
> > > > <br>
> > > > -- <br>
> > > > Roman Klochkov<br>
> > > <br>
> > > <br>
> > > <br>
> > > -- <br>
> > > Roman Klochkov<br>
> > <br>
> > <br>
> > <br>
> > -- <br>
> > Roman Klochkov<br>
> <br>
> <br>
> <br>
> -- <br>
> Roman Klochkov<br>
<br>
</div>
                        
                
                <base target="_self" href="https://e.mail.ru/">
        </div>

        
</div>


</div>
</blockquote>
<br>
<br>-- <br>Roman Klochkov<br></div>
</blockquote></div><br></body></html>