[racket] Best practices for classes

From: Matthew Butterick (mb at mbtype.com)
Date: Sat Oct 4 12:50:10 EDT 2014

I see your point. As a workaround, I suppose it's just as good to combine
these ideas and use `prop:procedure` to hook into the `get-list` method.
Then, instead of using 'class-instance' as a list, I can use
'(class-instance)',
and things like (member val (class-instance)) and (map proc
(class-instance)) will work as expected (= operating on the list inside the
class instance).



On Sat, Oct 4, 2014 at 8:13 AM, Robby Findler <robby at eecs.northwestern.edu>
wrote:

> There is no prop:list like that.
>
> Adding more prop:* features (like prop:list) has implications for code
> that you cooperate with. In particular, when you get something that
> answers #t to list?, then you can rest assured that calling 'car' or
> it is a very simple operation (doesn't invoke unknown code, involves
> just a pointer dereference and some simple checks in the machine,
> etc). If we had a prop:list, then you wouldn't know those things and
> thus you might have to treat simple list iterations with the same care
> that you treat calling into unknown code (like it might grab a
> continuation and return to you later etc).
>
> That said, I do think that our integration of generic operations and
> our standard library deserves some more care and perhaps redesign to
> make things hang together better. As it stands, we have some
> conveniences, but they are limited by backwards compatibility concerns
> (like the one in the previous paragraph). I have heard that some are
> considering this as part of "racket2" but I don't know how far along
> those plans are.
>
> Robby
>
>
>
> On Sat, Oct 4, 2014 at 10:01 AM, Matthew Butterick <mb at mbtype.com> wrote:
> > Thank you. The `prop:procedure` works as hoped, in that the class
> instance
> > becomes usable in any form that takes a procedure (including things like
> > map).
> >
> > The `prop:sequence` also works, but … what it seems I really want is
> > `prop:list`, which AFAICT doesn't exist (?)
> >
> > The class I'm making is basically a list wrapped with some state. So in
> > terms of the class interface, it would be very convenient to allow a
> class
> > instance to be used anywhere a list is used.
> >
> > The problem with `prop:sequence` is that now I have to use the special
> > sequence versions of list functions, or convert to a list explicitly with
> > `sequence->list`. In terms of class interface, this isn't an improvement
> > over just using a method like (send class-instance get-list).
> >
> >
> >
> > On Thu, Oct 2, 2014 at 7:43 PM, Alexander D. Knauth <
> alexander at knauth.org>
> > wrote:
> >>
> >> I don’t know if you can do it with generic interfaces (as in
> >> racket/generic),
> >> but you can make classes whose instances have struct-type properties
> such
> >> as prop:procedure and prop:sequence
> >> (using interfaces as in racket/class, not racket/generic)
> >>
> >> #lang racket
> >>
> >> (define proc<%>
> >>   (interface* ()
> >>               ([prop:procedure
> >>                 (lambda (this . args)
> >>                   (send/apply this proc args))])
> >>               proc))
> >>
> >> (define proc%
> >>   (class* object% (proc<%>)
> >>     (super-new)
> >>     (define/public (proc x)
> >>       (displayln "this is the proc method of proc%")
> >>       x)))
> >>
> >> (define seq<%>
> >>   (interface* ()
> >>               ([prop:sequence
> >>                 (lambda (this)
> >>                   (send this get-sequence))])
> >>               get-sequence))
> >>
> >> (define seq%
> >>   (class* object% (seq<%>)
> >>     (super-new)
> >>     (define/public (get-sequence)
> >>       (list 1 2 3))))
> >>
> >> > (define p (new proc%))
> >> > (p 1)
> >> this is the proc method of proc%
> >> 1
> >> > (define s (new seq%))
> >> > (sequence-for-each displayln s)
> >> 1
> >> 2
> >> 3
> >>
> >> On Oct 2, 2014, at 6:21 PM, Matthew Butterick <mb at mbtype.com> wrote:
> >>
> >> What's the best approach to:
> >>
> >> + defining a class whose instances can be used as procedures?
> >>
> >> (define ci (new proc-class%))
> >> (ci arg arg2 ... )
> >>
> >> + ... whose instances can be used as lists (or at least support direct
> >> iteration?)
> >>
> >> (define li (new listish-class%))
> >> (for-each displayln li)
> >> (map ci li)
> >>
> >> My intuition is "implement a generic interface..." But then it gets
> hazy.
> >>
> >>
> >>
> >>
> >> ____________________
> >>  Racket Users list:
> >>  http://lists.racket-lang.org/users
> >>
> >>
> >
> >
> > ____________________
> >   Racket Users list:
> >   http://lists.racket-lang.org/users
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20141004/a551bc41/attachment.html>

Posted on the users mailing list.