Last active
June 13, 2019 17:32
-
-
Save fiddlerwoaroof/74ce5e9a39100573a2801c78d620cb71 to your computer and use it in GitHub Desktop.
Static typable EP solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Two kinds of animals: dogs and cats | |
// | |
// I want greet and leave to be defined such that there are four | |
// different behaviors corresponding to each combination of dog and | |
// cat | |
// | |
class Animal { | |
receive_operation(operation) { | |
console.log("the animal is unresponsive"); | |
} | |
} | |
class Operation { | |
operate() { | |
console.log("the animal is unresponsive"); | |
} | |
} | |
class Turtle extends Animal {} | |
class Dog extends Animal { | |
receive_operation(operation) { | |
// This if statement is hard to add in an extensible fashion | |
if (operation instanceof Greet) { | |
console.log("the dog wags its tail joyfully"); | |
} else if (operation instanceof Leave) { | |
console.log("the dog looks very sad"); | |
} | |
} | |
} | |
class Cat extends Animal { | |
receive_operation(operation) { | |
if (operation instanceof Greet) { | |
console.log("the cat stands aloof"); | |
} else if (operation instanceof Leave) { | |
console.log("the cat purs happily"); | |
} | |
} | |
} | |
class Greet extends Operation {} | |
class Leave extends Operation {} | |
function operate(animal, operation) { | |
animal.receive_operation(operation); | |
} | |
function main() { | |
for (const animal of [new Cat(), new Dog(), new Turtle()]) { | |
for (const operation of [new Greet(), new Leave()]) { | |
operate(animal, operation); | |
} | |
} | |
} | |
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defpackage :fwoar.extend | |
(:use :cl ) | |
(:export )) | |
(in-package :fwoar.extend) | |
#| ------------- Begin Library ------------- |# | |
(defclass animal () | |
()) | |
(defclass operation () | |
()) | |
(defgeneric operate (animal operation) | |
#| This method ensures type safety: as long as we're given something in the domain of the function | |
(animal, operation) => effect}, we'll get a result. |# | |
(:method ((animal animal) (operation operation)) | |
(format *standard-output* "the animal is unresponsive~%"))) | |
(defclass turtle (animal) | |
()) | |
#| -------------- End Library -------------- |# | |
(defclass cat (animal) | |
(#| cat-specific members here |#)) | |
(defclass dog (animal) | |
(#| dog-specific members here |#)) | |
(defclass greet (operation) | |
()) | |
(defclass leave (operation) | |
()) | |
(defmethod operate ((animal cat) (operation greet)) | |
(format *standard-output* "the cat stands aloof~%")) | |
(defmethod operate ((animal cat) (operation leave)) | |
(format *standard-output* "the cat purs happily~%")) | |
(defmethod operate ((animal dog) (operation greet)) | |
(format *standard-output* "the dog wags its tail joyfully~%")) | |
(defmethod operate ((animal dog) (operation leave)) | |
(format *standard-output* "the dog looks very sad~%")) | |
(defun main () | |
(dolist (animal (list (make-instance 'cat) | |
(make-instance 'dog) | |
(make-instance 'turtle))) | |
(dolist (action (list (make-instance 'greet) | |
(make-instance 'leave))) | |
(visit animal action)))) #| ===> | |
FWOAR.EXTEND> (main) | |
the cat stands aloof | |
the cat purs happily | |
the dog wags its tail joyfully | |
the dog looks very sad | |
the animal is unresponsive | |
the animal is unresponsive | |
|# |
Kotlin does control-flow-sensitive type specialization which sort of fixes the issue I have with Java, at the cost of a bit of boilerplate:
https://gist.github.com/fiddlerwoaroof/b24b321ddcfb11470241326e4dd7552d#file-world-kt-L14-L21
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's kinda what I was thinking: https://gist.github.com/friedbrice/915addaf78b562c5038f12e6629c39f1#file-extend-java