[racket-dev] Generics updates

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Fri Aug 2 15:51:25 EDT 2013

Yes, this is an issue.  I kind of vaguely hint at it in the documentation,
and didn't get around to making it an explicit point -- I use the phrase
"implements" for things that have to be directly implemented, and
"supports" for sort of "transitive" implements.  I use in-set and things
like it in some of the fallbacks because the dependencies for set->stream
are somewhat complex, and I didn't want to repeat the logic in each and
every case; I wanted to just call set->stream.  At some point I tried to
make an indirect helper that did dependency checking and reported errors in
terms of the primary method being called, but it got a bit cumbersome.  I
probably should have seen through the better code and docs, but I sort of
hit a point of "I need to just push this and see how it goes".

So, for documenting this, off the top of my head I'd define tech terms
"implemented method" and "supported method" in the documentation for
define-generics, and refer to them as necessary in methods for gen:set and
so on.  That way, saying that, for instance, set-count is a supported
method whenever set->stream is a supported method, allows the documentation
to imply all the direct dependencies of set->stream on things that need to
be implemented methods, without having to restate them all.

For the implementation, what we have would fit the docs, and it might also
be possible to slightly improve the error messages with some refactoring.

Carl Eastlund


On Fri, Aug 2, 2013 at 3:43 PM, Stephen Chang <stchang at ccs.neu.edu> wrote:

> Actually, I am realizing that every derived method depends on
> set->stream, even the ones that don't document it (ie set-union,
> set-union!, set-intersect, set-intersect!, etc), since they use
> in-set.
>
> I was in the process of creating a patch for the docs to add the
> missing dependencies but I ran into an issue that I think warrants
> discussion.
>
> When the docs specifies dependencies for derived methods, there are
> actually two kinds that are being conflated.
>
> *** The first kind of dependency is stricter and requires the
> programmer to explicitly implement the required methods, and fallbacks
> do not count. In the code, this dependency is enforced with a call to
> the #:defined-predicated supplied to define-generics.
>
> Example:
>
> set-copy says it depends on set-clear and set-add!.
>
> Below is a set implementation that implements all the primitive
> methods plus set->stream. There exist set-clear and set-add! functions
> but set-clear is a fallback so set-copy wont work. Only if I
> explicitly implement set-clear will I get set-copy.
>
> (struct lstset (lst)
>   #:transparent
>   #:methods gen:set
>   [(define (set-member? s x) (match s [(lstset lst) (member x lst)]))
>    (define (set-add s x)
>      (match s
>        [(lstset lst)
>         (lstset (cons x (filter (λ (y) (not (equal? y x))) lst)))]))
>    (define (set-remove s x) (match s [(lstset lst) (lstset (remove x
> lst))]))
>    (define (set-add! s x) (void))
>    (define (set-remove! s x) (void))
>    (define (set->stream s) (lstset-lst s))])
>
> > (set-add (lstset '(1 2)) 4)
> (lstset '(4 1 2))
> > (set-clear (lstset '(1 2)))
> (lstset '())
> > (set-copy (lstset '(1 2 3)))
> . . set-copy: not implemented for (lstset '(1 2 3))
>
>
>
> *** The second kind of dependency is looser and allows fallbacks. For
> example set-count requires set->stream, but if I implement in-set,
> that is good enough.
>
>
> I guess my question is, is this a docs issue, or should the code have
> more calls to set-implements?
>
>
>
> On Fri, Aug 2, 2013 at 1:47 PM, Stephen Chang <stchang at ccs.neu.edu> wrote:
> >> With that in mind, I think it would make sense to move `set-first' and
> >> `set-empty?' to the primitive set (making it clear that they are
> >> optional, and can be derived from `set->stream' if need be). With those
> >> two in the primitive set, anything that implements all the primitives
> >> should get all the derived for free, right?
> >
> > Oh yeah, I like that better than moving set->stream to primitives
> > since they are more "standard" set operations.
> >
> > Carl, I dont see how guaranteeing some fallback implementations
> > affects allowing more efficient versions. I think most programmers
> > understand that the default implementation is probably not very
> > efficient.
> >
> >
> >
> >
> >
> >
> >>
> >> Vincent
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20130802/cc509e1b/attachment.html>

Posted on the dev mailing list.