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