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 <chanse...@gmail.com> 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 racket-users+unsubscr...@googlegroups.com.
> 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 racket-users+unsubscr...@googlegroups.com.
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