Один шаблон должен иметь объекты, которые представляют результат теста, и объекты, которые представляют блок для выполнения. Полученные объекты имеют переопределенные функции выбора, поэтому, если у Bool был выбор (T положительный, T отрицательный), Bool.TRUE вернет положительный аргумент, а Bool.FALSE вернет отрицательный. Наивные реализации языков семейства smalltalk работают так.
Чтобы закодировать ваш цикл while в этой форме, необходимо вызвать метод выбора в результате сравнения x и y, чтобы определить, вызывать ли блок внутри цикла while, и этот блок также использует сравнение и выбор. установить значение х. Более буквальным переводом было бы выбрать либо блок, который устанавливает x в z, либо блок, который ничего не делает; вместо этого он просто использует выбор, чтобы установить х обратно в то же значение.
Очевидно, что в этом простом случае это излишне и неэффективно.
public class WantonPolymorphism {
static class Int32 {
final int value;
Int32 ( final int value ) { this.value = value; }
Compare compare ( Int32 other ) {
// Java runs out of turtles at this point unless you use
// an enum for every value
if ( this.value < other.value ) return Compare.LESS;
if ( this.value > other.value ) return Compare.GREATER;
return Compare.EQUAL;
}
}
enum Compare {
LESS {
<T> T choose (T less, T equal, T greater) { return less; }
},
EQUAL {
<T> T choose (T less, T equal, T greater) { return equal; }
},
GREATER {
<T> T choose (T less, T equal, T greater) { return greater; }
};
abstract <T> T choose (T less, T equal, T greater) ;
}
interface Block { Block execute () ; }
/**
* Main entry point for application.
* @param args The command line arguments.
*/
public static void main (String...args) {
Block block = new Block() {
Int32 x = new Int32(4);
Int32 y = new Int32(3);
Int32 z = new Int32(2);
public Block execute () {
System.out.printf("x = %d, y = %d, z = %d\n", x.value, y.value, z.value);
return x.compare(y).choose(done, done, new Block () {
public Block execute () {
x = x.compare(z).choose(x,x,z);
return x.compare(y).choose(done, done, this);
}
});
}
Block done = new Block () {
public Block execute () {
System.out.printf("x = %d, y = %d, z = %d\n", x.value, y.value, z.value);
System.exit(0);
return this;
}
};
};
for(;;)
block = block.execute();
}
}