I don't know of a way to solve that problem using the Racket class system
alone, but here is a solution that uses traits instead, which allow you to
rename the hook methods after the fact so they don't collide.

  ;; ....
  (require racket/trait)

  (define secure-trait
    (trait
     (inherit needed-item)
     (define/override (can-open p)
       (println "secure-mixin can-open")
       (define item (needed-item))
       (cond
         ((not (send p has-item item)) (printf "You don't have the Key
~v\n" item)
          #f)
         (else (printf "Using Key... ~v\n" item)
               (super can-open p))))))

  (define locked-needed-trait
    (trait
     (define/public (needed-item)
       (println "locked-needed-mixin neededItem")
       the-key)))

  (define magic-needed-trait
    (trait
     (define/public (needed-item)
       (println "magic-needed-mixin neededItem")
       the-spell-book)))

  (define locked-mixin
    (trait->mixin
     (trait-rename (trait-sum secure-trait locked-needed-trait)
                   needed-item needed-item/locked)))

  (define magic-mixin
    (trait->mixin
     (trait-rename (trait-sum secure-trait magic-needed-trait)
                   needed-item needed-item/magic)))
  ;; ....

Ryan


On Sun, Aug 9, 2020 at 11:12 PM Siyuan Chen <[email protected]> wrote:

> Hi all,
>
> Recently I read the paper "Classes and Mixins" by Matthew Flatt, Shriram
> Krishnamurthi and Matthias Felleisen.
>
> In this paper, the authors presented MIXEDJAVA.
>
> In MIXEDJAVA,
>
>> A programmer implements mixins in exactly the same
>> way as a derived class, except that the programmer cannot
>> rely on the implementation of the mixin's superclass, only
>> on its interface. We consider this an advantage of mixins
>> because it enforces the maxim "program to an interface, not
>> an implementation".
>>
> It is very close to the mixin form in Racket, because we can specific
> interface in the mixin form:
>
> ```
> (mixin (interface-expr ...) (interface-expr ...)
>   class-clause ...)
> ```
>
> In Chapter 3, they also introduced an example (a maze adventure game, I
> called it LockedMagicDoor) which uses the system.
>
> My question is:
>
> Is it possible to implement LockedMagicDoor in Racket?
>
>
> I did some experiments but failed.
>
> See following code (or
> https://gist.github.com/chansey97/aecffabb2885c83fa040ba677bde5de4):
>
> ```
> #lang racket
>
> (define the-key 'the-key)
> (define the-spell-book 'the-spell-book)
>
> (define person%
>   (class object%
>     (init-field items h)
>     (super-new)
>
>     (define/public (has-item item)
>       (member item items))
>
>     (define/public (height)
>       h)
>     ))
>
> (define door<%> (interface () can-open can-pass))
>
> (define door-mixin
>   (mixin () (door<%>)
>     (super-new)
>
>     (define/public (can-open p)
>       (println "door% can-open")
>       #t)
>
>     (define/public (can-pass p)
>       (println "door% can-pass")
>       #t)
>     ))
>
> (define secure-door<%> (interface (door<%>) needed-item))
>
> (define secure-mixin
>   (mixin (door<%>) (secure-door<%>)
>     (super-new)
>
>     (define/public (needed-item) ;; error??
>       (println "secure-mixin needed-item")
>       #f)
>
>     (define/override (can-open p)
>       (println "secure-mixin can-open")
>       (define item (needed-item))
>       (cond
>         ((not (send p has-item item)) (printf "You don't have the Key
> ~v\n" item)
>                                       #f)
>         (else (printf "Using Key... ~v\n" item)
>               (super can-open p))))
>     ))
>
> (define locked-needed-mixin
>   (mixin (secure-door<%>) (secure-door<%>)
>     (super-new)
>     (define/override (needed-item)
>       (println "locked-needed-mixin neededItem")
>       the-key)
>     ))
>
> (define magic-needed-mixin
>   (mixin (secure-door<%>) (secure-door<%>)
>     (super-new)
>     (define/override (needed-item)
>       (println "magic-needed-mixin neededItem")
>       the-spell-book)
>     ))
>
> (define door%
>   (door-mixin object%))
>
> (define locked-mixin (compose locked-needed-mixin secure-mixin))
> (define magic-mixin (compose magic-needed-mixin secure-mixin))
>
> (define locked-magic-mixin (compose locked-mixin magic-mixin))
> (define locked-magic-door% (locked-magic-mixin door%))
>
> (define door (new locked-magic-door%))
> (send door can-open (new person% [items (list the-key the-spell-book)] [h
> 0.5]))
>
> ; class*: superclass already contains method
> ;   superclass: #<class:...agic-door-failed.rkt:62:2>
> ;   method name: needed-item
> ;   class name: ...agic-door-failed.rkt:36:2
>
> ```
>
> The problem is how to implement `secure-mixin`?
>
> Notice that since the `secure-mixin` is mixed into `locked-magic-door%`
> twice, there will be two `needed-item` methods in the inheritance chain, so
> they are naming conflict.
>
> However in MIXEDJAVA, they do not conflict:
>
>> Specifically, a composition m1 compose m2 contains two methods named
>> x if both m1 and m2 declare x and m1's inheritance interface does not
>> contain x. Both x methods are accessible in an instance of the composite
>> mixin since the object can be viewed specifically as an instance of m1 or
>> m2.
>>
> Can someone help me? (e.g. make some changes to this code above and let it
> work in Racket)
>
> Very thanks.
>
>
> I also attempt to use Inner to simulate the behavior of MIXEDJAVA:
>
> ```
> (define secure-mixin
>   (mixin (door<%>) (secure-door<%>)
>     (super-new)
>
>     (define/pubment (needed-item)
>       (println "secure-mixin needed-item")
>       #f)
>
>     (define/override (can-open p)
>       (println "secure-mixin can-open")
>       (define item (inner #f needed-item))
>       (cond
>         ((not (send p has-item item)) (printf "You don't have the Key
> ~v\n" item)
>                                       #f)
>         (else (printf "Using Key... ~v\n" item)
>               (super can-open p))))
>     ))
>
> (define locked-needed-mixin
>   (mixin (secure-door<%>) (secure-door<%>)
>     (super-new)
>     (define/augride (needed-item)
>       (println "locked-needed-mixin neededItem")
>       the-key)
>     ))
>
> (define magic-needed-mixin
>   (mixin (secure-door<%>) (secure-door<%>)
>     (super-new)
>     (define/augride (needed-item)
>       (println "magic-needed-mixin neededItem")
>       the-spell-book)
>     ))
> ```
>
> But still failed:
>
> ; class*: superclass already contains method
> ;   superclass: #<class:...y-pubment-failed.rkt:62:2>
> ;   method name: needed-item
>
> See https://gist.github.com/chansey97/264d3435a8f506153709cc9804227fdf
>
> PS: I also tried `overment` and `augment` for the `needed-item` in
> `secure-mixin`, but failed as well (although the error messages are
> different).
>
>
> IMO, it seems that `Inner` can be used to simulate the behavior of
> MIXEDJAVA, but I don't know how to do it.
>
> Notice that in the paper, "Super and Inner — Together at Last!" by David
> S. Goldberg, Robert Bruce Findler and Matthew Flatt, the authors originally
> used `beta` and `java` to mark the methods, no need `pubment` a method
> first. In that model, it may not be conflicting (just a very immature
> opinion).
>
> So can we use the `Inner` to simulate the behavior of MIXEDJAVA?
>
>
> Another question:
>
> In MIXEDJAVA, there is a `view` concept, which is very powerful.
>
> Can we get the corresponding equivalent in Racket?
>
> Very thanks.
>
>
> Best regards,
>
> Siyuan Chen
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAHWTsYnZCbRt2U%2Bt7JQPNt7rBNQAwSy8_4ycUqNkQ23ZOdncvQ%40mail.gmail.com
> <https://groups.google.com/d/msgid/racket-users/CAHWTsYnZCbRt2U%2Bt7JQPNt7rBNQAwSy8_4ycUqNkQ23ZOdncvQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CANy33qmXNcMehoZP71hpNdXq23NbqAhX5DmvZCvDTa1WH%2BAp4A%40mail.gmail.com.

Reply via email to