Skip to content

Instantly share code, notes, and snippets.

@tarao
Created April 15, 2010 16:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tarao/367299 to your computer and use it in GitHub Desktop.
Save tarao/367299 to your computer and use it in GitHub Desktop.
Enumerating prime numbers in Featherweight Java
////////////////////////////////////////////////
// Lazy evaluation
class Obj extends Object {
Obj(){ super(); } Obj eval(){ return this; }
}
////////////////////////////////////////////////
// Error indicator
class Error extends Obj { Error(){ super(); } }
////////////////////////////////////////////////
// Boolean
class Bool extends Obj {
Bool(){ super(); }
Bool neg(){ return new False(); }
Bool or(Obj b){ return this; }
Bool and(Obj b){ return (Bool)b.eval(); }
Obj cond(Obj thn, Obj els){ return thn.eval(); }
}
class True extends Bool { True(){ super(); } }
class False extends Bool {
False(){ super(); }
Bool neg(){ return new True(); }
Bool or(Obj b){ return (Bool)b.eval(); }
Bool and(Obj b){ return this; }
Obj cond(Obj thn, Obj els){ return els.eval(); }
}
////////////////////////////////////////////////
// Natural number
class N extends Obj {
N(){ super(); }
N pre(){ return (N)(Obj)new Error(); }
N suc(){ return new S(this); }
N add(N m){ return m; }
N sub(N m){ return (N)m.isZero().cond(this, new Error()); }
N mul(N m){ return this; }
N div(N m){ return (N)this.divRem(m).car(); }
N mod(N m){ return (N)this.divRem(m).cdr().car(); }
List divRem(N m) {
return (List)m.isZero().cond(new List().one(new Error()),
new List().two(new Z(), new Z()));
}
Bool isZero(){ return new True(); }
Bool isSucOf(N m){ return new False(); }
Bool eq(N m){ return m.isZero(); }
Bool ne(N m){ return this.eq(m).neg(); }
Bool gt(N m){ return new False(); }
Bool lt(N m){ return m.gt(this); }
Bool ge(N m){ return this.eq(m).or(this.gt(m)); }
Bool le(N m){ return m.ge(this); }
}
class Z extends N { Z(){ super(); } }
class S extends Z {
N n; S(N n){ super(); this.n=n; }
N pre(){ return this.n; }
N add(N m){ return this.n.add(m).suc(); }
N sub(N m) { return (N)m.isZero().cond(this, new SubElse(this.n, m)); }
N mul(N m){ return (N)m.add(this.n.mul(m)); }
List divRem(N m) {
return (List)m.isZero().cond(new List().one(new Error()),
new DivRemElse1(this, m));
}
Bool isZero(){ return new False(); }
Bool isSucOf(N m){ return m.eq(this.n); }
Bool eq(N m){ return m.isSucOf(this.n); }
Bool gt(N m){ return this.n.ge(m); }
}
class SubElse extends Obj {
N n; N m; SubElse(N n, N m){ super(); this.n=n; this.m=m; }
Obj eval(){ return this.n.sub(this.m.pre()); }
}
class DivRemElse1 extends Obj {
N n; N m; DivRemElse1(N n, N m){ super(); this.n=n; this.m=m; }
Obj eval() {
return this.n.lt(this.m).cond(new List().two(new Z(), this.n),
new DivRemElse2(this.n, this.m));
}
}
class DivRemElse2 extends DivRemElse1 {
DivRemElse2(N n, N m){ super(n, m); }
List sucCar(List l){ return new Cons(((N)l.car()).suc(), l.cdr()); }
Obj eval() { return this.sucCar(this.n.sub(this.m).divRem(this.m)); }
}
////////////////////////////////////////////////
// List
class List extends Obj {
List(){ super(); }
Bool isNil(){ return new True(); }
Obj car(){ return this; }
List cdr(){ return new List(); }
List one(Obj a){ return new Cons(a, new Nil()); }
List two(Obj a, Obj b){ return new Cons(a, new List().one(b)); }
}
class Nil extends List { Nil(){ super(); } }
class Cons extends List {
Obj car; List cdr;
Cons(Obj car, List cdr){ super(); this.car=car; this.cdr=cdr; }
Obj car(){ return this.car; }
Bool isNil(){ return new False(); }
List cdr(){ return this.cdr; }
}
////////////////////////////////////////////////
// Infinite sequence
class Seq extends Obj {
Obj val; Next next;
Seq(Obj val, Next next){ super(); this.val=val; this.next=next; }
Obj car(){ return this.val; }
Seq cdr(){ return this.next.get(); }
List take(N n) {
return (List)n.isZero().cond(new Nil(), new Take(n, this));
}
}
class Next extends Obj {
Next(){ super(); } Seq get(){ return new Seq(new Obj(), this); }
}
class Take extends Obj {
N n; Seq s; Take(N n, Seq s){ super(); this.n=n; this.s=s; }
Obj eval() {
return new Cons(this.s.car(), this.s.cdr().take(this.n.pre()));
}
}
////////////////////////////////////////////////
// Generating prime numbers
class Sift extends Next {
N n; Seq s; Sift(N n, Seq s){ super(); this.n=n; this.s=s; }
Seq get() {
return (Seq)((N)this.s.car()).mod(this.n).isZero()
.cond(new SiftThen(this), new SiftElse(this));
}
}
class SiftThen extends Obj {
Sift si; SiftThen(Sift si){ super(); this.si=si; }
Obj eval(){ return new Sift(this.si.n, this.si.s.cdr()).get(); }
}
class SiftElse extends Obj {
Sift si; SiftElse(Sift si){ super(); this.si=si; }
Obj eval(){ return new Seq(this.si.s.car(), new SiftElseNext(this)); }
}
class SiftElseNext extends Next {
SiftElse se; SiftElseNext(SiftElse se){ super(); this.se=se; }
Seq get(){ return new Sift(this.se.si.n, this.se.si.s.cdr()).get(); }
}
class Sieve extends Next {
Seq s; Sieve(Seq s){ super(); this.s=s; }
Seq get(){ return new Seq(this.s.car(), new SieveNext(this)); }
}
class SieveNext extends Next {
Sieve si; SieveNext(Sieve si){ super(); this.si=si; }
Seq get() {
return new Sieve(new Sift((N)this.si.s.car(),
this.si.s.cdr()).get()).get();
}
}
class PrimeSeq extends Next {
PrimeSeq(){ super(); }
N n2(){ return new Z().suc().suc(); } N n3(){ return this.n2().suc(); }
Seq get() {
return new Sieve(new Seq(this.n2(), new From2(this.n3()))).get();
}
}
class From2 extends Next {
N n; From2(N n){ super(); this.n=n; }
Seq get(){ return new Seq(this.n, new From2(this.n.suc().suc())); }
}
////////////////////////////////////////////////
// Test
class Test {
static class PP {
static Integer toInteger(N n) {
int i=0;
for (; n instanceof S; i++) n = ((S)n).n;
return new Integer(i);
}
static String toString(Object obj) {
if (obj instanceof True) {
return "true";
} else if (obj instanceof False) {
return "false";
} else if (obj instanceof N) {
return ""+toInteger((N)obj);
} else if (obj instanceof List) {
List ls = (List)obj;
if (!(ls instanceof Cons)) return "[]";
String s = toString(ls.car());
for (ls = ls.cdr(); ls instanceof Cons; ls = ls.cdr()) {
s += "," + toString(ls.car());
}
return "[" + s + "]";
}
return "unknown: " + obj.getClass().getName();
}
}
public static void main(String[] args) {
N two = new Z().suc().suc();
N eight = two.mul(two).mul(two);
List ls = new PrimeSeq().get().take(eight.mul(eight));
System.out.println(PP.toString(ls));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment