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.

