[racket] Best practices for classes
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
>