Created
November 23, 2011 17:38
-
-
Save synther/1389324 to your computer and use it in GitHub Desktop.
Attempt to make a lambda-like construction in Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package lambdatest; | |
import java.lang.reflect.InvocationTargetException; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
/** | |
* Попытка сделать что-то похожее на лямбды не используя паттерн Command. | |
* Треш, кишки и расчлененка. | |
* | |
* Выполнение примера: | |
* run: | |
* foreach: | |
* = 1 | |
* = 2 | |
* = 3 | |
* = 4 | |
* = 5 | |
* | |
* sum: | |
* 15 | |
* BUILD SUCCESSFUL (total time: 0 seconds) | |
* | |
* Проблемы, которые пока не решены: | |
* - дурацкий if (!init) { | |
* - ни разу не thread-safe | |
* - при перемещении lambda-классов в другой пакет все ломается | |
* | |
* @author synther | |
*/ | |
public class LambdaTest { | |
public static void main(String[] args) throws Exception { | |
final Integer[] nums = new Integer[]{1, 2, 3, 4, 5}; | |
System.out.println("foreach:"); | |
forEach(nums, new A1<Object, Object>() {{if (!init) { | |
System.out.println("= " + x1); | |
}}}); | |
System.out.println(""); | |
System.out.println("sum:"); | |
int sum = fold(nums, new A2<Integer, Integer, Integer>(){{if (!init) { | |
result(x1 + x2); | |
}}}); | |
System.out.println(sum); | |
} | |
static void forEach(Object[] objects, A1<Object, Object> action) { | |
for (Object object : objects) { | |
action.apply(object); | |
} | |
} | |
static int fold(Integer[] integers, A2<Integer, Integer, Integer> action) { | |
if (integers.length == 0) { | |
return 0; | |
} | |
int result = integers[0]; | |
for (int i = 1; i < integers.length; i++) { | |
result = action.apply(result, integers[i]); | |
} | |
return result; | |
} | |
} | |
class A<R> extends LambdaCore<R, Object, Object, Object> { | |
public R apply() { | |
return apply(new Object[]{}); | |
} | |
} | |
class A1<R, T1> extends LambdaCore<R, T1, Object, Object> { | |
protected T1 x1; | |
public R apply(T1 arg1) { | |
return apply(new Object[]{arg1}); | |
} | |
} | |
class A2<R, T1, T2> extends LambdaCore<R, T1, T2, Object> { | |
protected T1 x1; | |
protected T2 x2; | |
public R apply(T1 arg1, T2 arg2) { | |
return apply(new Object[]{arg1, arg2}); | |
} | |
} | |
class A3<R, T1, T2, T3> extends LambdaCore<R, T1, T2, T3> { | |
protected T1 x1; | |
protected T2 x2; | |
protected T2 x3; | |
public R apply(T1 arg1, T2 arg2) { | |
return apply(new Object[]{arg1, arg2}); | |
} | |
} | |
abstract class LambdaCore<R, T1, T2, T3> { | |
final protected boolean init; | |
private R resultValue; | |
private static Object params = null; | |
public LambdaCore() { | |
if ("newInstance0".equals(Thread.currentThread().getStackTrace()[4].getMethodName())) { | |
// Предполагаем что вызвано из apply() | |
try { | |
Object[] paramsArray = (Object[]) params; | |
if (paramsArray != null) { | |
if (paramsArray.length >= 1) { | |
this.getClass().getSuperclass().getDeclaredField("x1").set(this, (T1) (paramsArray[0])); | |
} | |
if (paramsArray.length >= 2) { | |
this.getClass().getSuperclass().getDeclaredField("x2").set(this, (T2) (paramsArray[1])); | |
} | |
if (paramsArray.length >= 3) { | |
this.getClass().getSuperclass().getDeclaredField("x3").set(this, (T3) (paramsArray[2])); | |
} | |
} | |
} catch (IllegalArgumentException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (IllegalAccessException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (NoSuchFieldException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (SecurityException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} | |
init = false; | |
} else { | |
// Предполагаем что вызвано при создании лямбды. Нужно предвратить выполнение | |
// конструктора анонимного класса | |
init = true; | |
} | |
} | |
protected R apply(Object... args) { | |
try { | |
params = args; | |
LambdaCore newInstance = this.getClass().getDeclaredConstructor().newInstance(); | |
return (R) newInstance.resultValue; | |
} catch (InstantiationException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (IllegalAccessException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (IllegalArgumentException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (InvocationTargetException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (NoSuchMethodException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (SecurityException ex) { | |
Logger.getLogger(LambdaCore.class.getName()).log(Level.SEVERE, null, ex); | |
} | |
return null; | |
} | |
protected void result(R r) { | |
this.resultValue = r; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment