Closed jiacai2050 closed 8 years ago
When writing a function over a datatype, place a method in each of the variants that make up the datatype. If a field of a variant belongs to the same datatype, the method may call the corresponding method of the field in computing the function.
上图是第二章中涉及到的类的关系
The third bit of advice
When writing a function that returns values of a datatype, use new to create these values.
The fourth bit of advice
When writing several functions for the same self-referential datatypes, use visit protocols so that all method can be found in one class
The sixth bit of advice
When the additional consumed values change for a self-referential use of a visitor, don't forget to create a new value.
package chap5.version1;
class RemV {
PieD forTop(Object t, PieD r, Object o) {
if (t.equals(o)) {
return r.rem(this, t);
} else {
return new Top(t, r.rem(this, o));
}
}
PieD forBot(Object o) {
return new Bot();
}
}
class SubstV {
PieD forTop(Object t, PieD r, Object n, Object o) {
if (t.equals(o)) {
return new Top(n, r.subst(this, n, o) );
} else {
return new Top(t, r.subst(this, n, o) );
}
}
PieD forBot(Object n, Object o) {
return new Bot();
}
}
abstract class PieD {
abstract PieD rem(RemV remFn, Object o);
abstract PieD subst(SubstV substFn, Object n, Object o);
}
class Top extends PieD {
Object t;
PieD r;
public Top(Object t, PieD r) {
this.t = t;
this.r = r;
}
@Override
PieD rem(RemV remFn, Object o) {
return remFn.forTop(t, r, o);
}
@Override
PieD subst(SubstV substFn, Object n, Object o) {
return substFn.forTop(t, r, n, o);
}
}
class Bot extends PieD {
@Override
PieD rem(RemV remFn, Object o) {
return remFn.forBot(o);
}
@Override
PieD subst(SubstV substFn, Object n, Object o) {
return substFn.forBot(n, o);
}
}
package chap5.version2;
class RemV {
Object o;
PieD forTop(Object t, PieD r) {
if (t.equals(o)) {
return r.rem(this);
} else {
return new Top(t, r.rem(this));
}
}
PieD forBot() {
return new Bot();
}
}
//In functional programming, a visitor with fields is called a closure ( or a high-order function),
//which would be the result of applying a curried version of subst.
class SubstV {
Object n;
Object o;
PieD forTop(Object t, PieD r) {
if (t.equals(o)) {
return new Top(n, r.subst(this));
} else {
return new Top(t, r.subst(this));
}
}
PieD forBot() {
return new Bot();
}
public SubstV(Object n, Object o) {
super();
this.n = n;
this.o = o;
}
}
abstract class PieD {
abstract PieD rem(RemV remFn);
abstract PieD subst(SubstV substFn);
}
class Top extends PieD {
Object t;
PieD r;
public Top(Object t, PieD r) {
this.t = t;
this.r = r;
}
@Override
PieD rem(RemV remFn) {
return remFn.forTop(t, r);
}
@Override
PieD subst(SubstV substFn) {
return substFn.forTop(t, r);
}
}
class Bot extends PieD {
@Override
PieD rem(RemV remFn) {
return remFn.forBot();
}
@Override
PieD subst(SubstV substFn) {
return substFn.forBot();
}
}
class Main {
public static void main(String[] args) {
new Top(new Integer(3),
new Top(new Integer(2),
new Top(new Integer(3),
new Bot())))
.subst(new SubstV(
new Integer(5),
new Integer(3)));
}
}
package chap5.version3;
class RemV implements PieVisitorI {
Object o;
public RemV(Object o) {
this.o = o;
}
@Override
public PieD forBot() {
return new Bot();
}
@Override
public PieD forTop(Object t, PieD r) {
if (t.equals(o)) {
return r.accept(this);
} else {
return new Top(t, r.accept(this));
}
}
}
// In functional programming, a visitor with fields is called a closure ( or a
// high-order function),
// which would be the result of applying a curried version of subst.
class SubstV implements PieVisitorI {
Object n;
Object o;
public PieD forTop(Object t, PieD r) {
if (t.equals(o)) {
return new Top(n, r.accept(this));
} else {
return new Top(t, r.accept(this));
}
}
public PieD forBot() {
return new Bot();
}
public SubstV(Object n, Object o) {
super();
this.n = n;
this.o = o;
}
}
class LtdSubst implements PieVisitorI {
int c;
Object n;
Object o;
@Override
public PieD forBot() {
return new Bot();
}
@Override
public PieD forTop(Object t, PieD r) {
if (0 == c) {
return new Top(t, r);
} else {
if (o.equals(t)) {
return new Top(n, r.accept(new LtdSubst(c - 1, n, o)));
} else {
return new Top(t, r.accept(this));
}
}
}
public LtdSubst(int c, Object n, Object o) {
super();
this.c = c;
this.n = n;
this.o = o;
}
}
interface PieVisitorI {
PieD forBot();
PieD forTop(Object t, PieD r);
}
abstract class PieD {
abstract PieD accept(PieVisitorI ask);
}
class Top extends PieD {
Object t;
PieD r;
public Top(Object t, PieD r) {
this.t = t;
this.r = r;
}
@Override
PieD accept(PieVisitorI ask) {
return ask.forTop(ask, r);
}
}
class Bot extends PieD {
@Override
PieD accept(PieVisitorI ask) {
return ask.forBot();
}
}
class Main {
public static void main(String[] args) {
}
}
The seventh bit of advice
When desgining vistor protocols for many types, create a unifying protocol using Object.
The eighth bit of advice:
When extending a class, use overriding to enrich its functionality.
The ninth bit of advice:
If a datatype may have to be extended, be forward looking and use a constructor-like (overridable) method so that visitors can be extended, too.
the tenth bit of advice
when modifications to objects are needed, use a class to insulate the operations that modify objects. Otherwise aware the consequences of your actions.
Programming requires two kinds of knowledge:
The first of these if the more difficult intellectual task. If you understand the material in this book, you have masterd that challenge. Still, it would be worth your time to develop a fuller understanding of all capabilities in Java--this requires getting aceess to a running Java system and mastering those idosynrasies.
Chap 1. Modern Toys
The first bit of advice