[plt-scheme] Re: Multiple inheritance problem with mixins

From: Daniel Pinto de Mello e Silva (daniel.silva at gmail.com)
Date: Thu Feb 3 00:18:25 EST 2005

On Wed, 2 Feb 2005 22:26:02 -0600, Robby Findler <robby at cs.uchicago.edu> wrote:
> This problem in mixins does exist in general (see the LockedMagicDoor
> example in http://www.ccs.neu.edu/scheme/pubs/tr97-293.pdf) but I think
> you've simplified the example so much as to remove the real motivation?
> 

Yeah.  I don't get to define the-class%.  DrScheme does that, and I
provide it mixins through the tool interface like this:

(drscheme:get/extend:extend-definitions-text
tab-completion-definitions-text-mixin)

I have three different tools that extend the definitions-text.  They
all used to be defined as one mixin, and I'm now refactoring them into
three components: compile-on-save, online-error-checking, and
tab-completion.

The compile-on-save and online-error-checking components both happen
to either expand or compile code in the background and display error
messages in a window.  When their code lived together, they used the
same threading mechanism for keeping only one expansion thread running
at any time, and the same error handler for syntax errors that would
color the broken program text.

The online-error-checking and the tab-completion components both make
use of program expansion information.  Since online-error-checking is
constantly expanding code, once it finishes a successful expansion
with no syntax errors, it saves the syntax object in a field.  The
tab-completion component reads that syntax object to pick out
top-level definitions and module requires.  They also share some
utility methods for figuring out what the current directory should be
during expansion and when looking up required modules.

So I have five mixins, three for the components and two that are each
shared by a pair of components.  Each component has no control over
what other mixins might be applied (the user might have only 1 of the
tools installed), so right now I check for "implements?" at the shared
mixin functions.

By the way, the shared mixins have no use to the outside world -- is
declaring methods "public" the only way to allow inheritance?

Daniel


> In any case, I think that the proper fix for your first post's code is
> to just not call the mixin from inside the definition of another mixin.
> Instead just mix shared-mixin in once, at the end.
> 
> Like this:
> 
> (require (lib "macro.ss" "framework"))
> 
> (define shared<%>
>   (interface ()
>     get-expansion
>     set-expansion))
> 
> (define shared-mixin
>   (mixin () (shared<%>)
>     (super-new)
>     (define/public (set-expansion x) (void))
>     (define/public (get-expansion) (void))))
> 
> (define tab-completion
>   (mixin (shared<%>) ()
>     (class %
>       (super-new)
>       (inherit set-expansion get-expansion))))
> 
> (define online-error-reporting
>   (mixin (shared<%>) ()
>     (super-new)
>     (inherit set-expansion get-expansion)))
> 
> (define the-class%
>   (online-error-reporting
>    (tab-completion
>     (shared-mixin
>      object%))))
> 
> Robby
> 
> At Thu, 3 Feb 2005 12:55:14 +0900, Daniel Pinto de Mello e Silva wrote:
> >   For list-related administrative tasks:
> >   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> >
> > Nevermind :)
> >
> > (define sm<%>
> >    (interface () get-expansion set-expansion))
> >
> > (define (shared-mixin %)
> >   (if (implementation? % sm<%>)
> >       %
> >      (class %
> >         (super-new)
> >         (define/public (set-expansion x) (void))
> >         (define/public (get-expansion) (void)))))
> >
> >
> > Daniel
> >
> >
> > On Thu, 3 Feb 2005 12:44:21 +0900, Daniel Pinto de Mello e Silva
> > <daniel.silva at gmail.com> wrote:
> > > Hi,
> > > I have some shared functionality between two mixins that shouldn't
> > > know about each other.  I wanted to implement the shared functionality
> > > as another mixin, but I get an error:
> > > class*: superclass already contains method: m for class: stdin::57
> > >
> > > Is there a good way to abstract out shared functionality from two
> > > mixins?  This is the distilled example:
> > >
> > > (require (lib "class.ss"))
> > >
> > > (define (shared-mixin %)
> > >   (class %
> > >      (super-new)
> > >      (define/public (set-expansion x) (void))
> > >      (define/public (get-expansion) (void))))
> > >
> > > (define (tab-completion %)
> > >   (class (shared-mixin %)
> > >      (super-new)
> > >      (inherit set-expansion get-expansion)))
> > >
> > > (define (online-error-reporting %)
> > >   (class (shared-mixin %)
> > >      (super-new)
> > >      (inherit set-expansion get-expansion)))
> > >
> > > (define the-class% (online-error-reporting (tab-completion object%)))
> > >
> > >
> > > Daniel
> > >
>



Posted on the users mailing list.