[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: accumulator generator (Java)



Another (less elegant) way in Java would be to have each invocation of foo(n) 
return a Method that takes an argument 'i' and accumulates this value with n.  
We need to reload the returned Method's class (named Inc) at each invocation.  
To emulate closure-like behavior for every invocation of 'foo' a new definition 
of class Inc is reloaded, an instance is created, so the Method returned will 
delegate to that instance.  The following horrid code demonstrates...

import java.io.*;
import java.lang.reflect.*;

public class Accumulator {
  public static void main(String[] args) throws Exception {
    Method[] ms = new Method[3];
    for (int i = 0; i < ms.length; i++) {
      ms[i] = foo(i);
    }
    for (int i = 0; i < ms.length; i++) {
      for (int j = 0; j < 3; j++) {
	System.out.println(i + "," + j + ": " + 
			   ms[i].invoke(null, new Object[]{new Integer(j)}));
      }
    }
  }

  static class Inc {
    public int n;
    public static Inc instance;
    public Inc(int n) { this.n = n; }
    private int inc(int i) { return n += i; }
    public static int foo(int i) { return instance.inc(i); }
  }

  static Method foo(int n) throws Exception {
    // Load the new class
    Class incClass = new ClassLoader(null) {
	final static byte[] bytes = {
	  -54,-2,-70,-66,0,3,0,45,0,31,7,0,2,1,0,15,65,99,99,117,
	  109,117,108,97,116,111,114,36,73,110,99,7,0,4,1,0,16,106,97,118,
	  97,47,108,97,110,103,47,79,98,106,101,99,116,1,0,8,105,110,115,116,
	  97,110,99,101,1,0,17,76,65,99,99,117,109,117,108,97,116,111,114,36,
	  73,110,99,59,1,0,1,110,1,0,1,73,1,0,3,105,110,99,1,0,
	  4,40,73,41,73,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,
	  117,109,98,101,114,84,97,98,108,101,12,0,7,0,8,9,0,1,0,13,
	  1,0,3,102,111,111,12,0,5,0,6,9,0,1,0,16,12,0,9,0,
	  10,10,0,1,0,18,1,0,6,60,105,110,105,116,62,1,0,4,40,73,
	  41,86,12,0,20,0,23,1,0,3,40,41,86,10,0,3,0,22,1,0,
	  10,83,111,117,114,99,101,70,105,108,101,1,0,16,65,99,99,117,109,117,
	  108,97,116,111,114,46,106,97,118,97,1,0,12,73,110,110,101,114,67,108,
	  97,115,115,101,115,7,0,29,1,0,11,65,99,99,117,109,117,108,97,116,
	  111,114,1,0,3,73,110,99,0,32,0,1,0,3,0,0,0,2,0,9,
	  0,5,0,6,0,0,0,1,0,7,0,8,0,0,0,3,0,18,0,9,
	  0,10,0,1,0,11,0,0,0,36,0,3,0,2,0,0,0,12,42,89,
	  -76,0,14,27,96,90,-75,0,14,-84,0,0,0,1,0,12,0,0,0,6,
	  0,1,0,0,0,28,0,9,0,15,0,10,0,1,0,11,0,0,0,32,
	  0,2,0,1,0,0,0,8,-78,0,17,26,-73,0,19,-84,0,0,0,1,
	  0,12,0,0,0,6,0,1,0,0,0,29,0,1,0,20,0,21,0,1,
	  0,11,0,0,0,42,0,2,0,2,0,0,0,10,42,-73,0,24,42,27,
	  -75,0,14,-79,0,0,0,1,0,12,0,0,0,14,0,3,0,0,0,27,
	  0,4,0,27,0,9,0,27,0,2,0,25,0,0,0,2,0,26,0,27,
	  0,0,0,10,0,1,0,1,0,28,0,30,0,8,
	};
	protected Class findClass(String name) throws ClassNotFoundException {
	  return super.defineClass(name, bytes, 0, bytes.length);
	}
      }.loadClass("Accumulator$Inc");
    
    // Set Inc's n value
    Constructor ctor = incClass.getConstructor(new Class[]{int.class});
    ctor.setAccessible(true);
    Object instance = ctor.newInstance(new Object[]{new Integer(n)});
    Field f = incClass.getField("instance");
    f.setAccessible(true);
    f.set(null, instance);

    // Get the new method
    Method method = incClass.getMethod("foo", new Class[]{int.class});
    method.setAccessible(true);
    return method;
  }

}

... and outputs

0,0: 0
0,1: 1
0,2: 3
1,0: 1
1,1: 2
1,2: 4
2,0: 2
2,1: 3
2,2: 5

showing that each method returned from 'foo' is, in fact, unique.

Jeff


---
Jeffrey Palm --> http://www.cs.colorado.edu/~jdp