Previous    Next


To make the new language Fun-MiniJava, we add function types to MiniJava:

ClassDecl → type id = TypeExp ;
 TypeExpTypeExp -> TypeExp
 → ( TypeList ) -> TypeExp
 → ( TypeExp )
 → Type TypeListTypeExp TypeRest*
 TypeRest →, TypeExp

The type int->String is the type of functions that take a single integer argument and return a string result (assuming a class String is declared). The type (int,String)->int[] describes functions that take two arguments (one integer, one string) and return an array-of-integers result. Any variable can have a functional type; functions can be passed as arguments and returned as results. Thus, the type (int->int)->(int)->int is perfectly legal; the -> operator is right-associative, so this is the type of functions that take an int->int argument and return an int->int result. We also modify the format of a CALL expression, so that the function being called is an arbitrary expression, without the .methodname component, and so that a method itself can be the result of an expression:

ExpExp ( ExpList )
ExpExp . id

If v is an object of a class with a method int m(int[]), then the expression v.m evaluates to a function value of type (int[])->int. Evaluating v.m does not call the method. We permit variable declarations and function (method) declarations at the beginning of a compound statement (i.e., functions are nested). We remove the if statement and add an if expression: That is, (if (E) B else C) evaluates E, and then evaluates B if E is true, otherwise evaluates C. The value of the entire if expression is the value of B or C.

MethodDeclpublic Type id ( FormalList ) Compound
 Compound → { VarDecl* MethodDecl* Statement* return Exp ;}
 ExpCompoundif ( Exp ) Exp else Exp

Finally, we interpret the meaning of return differently: Instead of producing the result for an entire function body, it produces the result of its own compound statement. Thus, the expression {return 3;}+{return 4;} evaluates to 7. Program 15.1 illustrates the use of function types. The function add takes an integer argument n and returns a function h. Thus, addFive is a version of h whose n variable is 5, but addSeven is a function h(x) = 7 + x. The need for each different instance of h to "remember" the appropriate value for a nonlocal variable n motivates the implementation technique of closures, which is described later.

A FunJava program.
type intfun = int -> int;
class C {
 public intfun add(n: int) {
 public int h(int m) { return n+m;}
 return h;
 public intfun twice(f: intfun) {
 public int g(int x) {return f(f(x));}
 return g;
 public int test() {
 intfun addFive = add(5);
 intfun addSeven = add(7);
 int twenty = addFive(15);
 int twentyTwo = addSeven(15);
 intfun addTen = twice(addFive);
 int seventeen = twice(add(5))(7);
 intfun addTwentyFour = twice(twice(add(6)));
 return addTwentyFour(seventeen);

Java End example

The function twice takes an argument f that is a function from int to int, and the result of twice(f) is a function g that applies f twice. Thus, addTen is a function g(x) = addFive(addFive(x)). Each instance of g(x) needs to remember the right f value, just as each instance of h needs to remember n.

JaVaScreenshot Previous    Next