// The factoral function in continuation-passing style, in Java

// sestoft@dina.kvl.dk 2002-04-03, 2003-03-19

 

// A Cont object is a continuation: it has a method k that given the

// result of a subcomputation will return the final result:

 

interface Cont {

  int k(int v);

}

 

// Calling the two versions of factorial:

 

class Factorial {

  public static void main(String[] args) {

    int n = Integer.parseInt(args[0]);

    System.out.println(facc(n,

                            new Cont() {

                                public int k(int v) {

                                  return v;

                                }

                              }));

    System.out.println(faci(n,

                            new Cont() {

                                public int k(int v) {

                                  return v;

                                }

                              }));

  }

 

  // A continuation-passing version of factorial.  This is a straight

  // translation of the Standard ML version:

 

  static int facc(final int n, final Cont cont) {

    if (n == 0)

      return cont.k(1);

    else

      return facc(n-1,

                  new Cont() {

                      public int k(int v) {

                        return cont.k(n * v);

                      }

                    });

  }

 

  // Another continuation-passing version of factorial.  Since facc

  // above is tail-recursive, it can be rewritten as a loop.  This

  // shows how it builds up a continuation and finally applies it:

 

  static int faci(int n, Cont cont) {

    while (n != 0) {

      cont = new FacCont(n, cont);

      n--;

    }

    return cont.k(1);

  }

}

     

// Auxiliary class to implement faci.  Needed for Java-technical

// reasons; a local inner class can refer only to `final' variables in

// the enclosing method, but faci must update the cont variable in the

// loop.

 

class FacCont implements Cont {

  private final int n;

  private final Cont cont;

 

  public FacCont(int n, Cont cont) {

    this.n = n; this.cont = cont;

  }

 

  public int k(int v) {

    return cont.k(n * v);

  }

}