Javaでmapとかinjectとか
こういうものを用意して、
public class Functional { public static <T> Functional.Iterable<T> from(java.lang.Iterable<T> from) { return new Functional.Iterable<T>(from); } public static interface Mapper<T1, T2> { public T2 map(T1 x); } public static interface Injector<T1, T2> { public T2 inject(T1 x, T2 a); } public static class Iterable<T> implements java.lang.Iterable<T> { public Iterator<T> iterator() { return raw.iterator(); } public Iterable(java.lang.Iterable<T> raw) { this.raw = raw; } private final java.lang.Iterable<T> raw; public <T2> Functional.Iterable<T2> map(final Mapper<T, T2> mapper) { return new Functional.Iterable<T2>(new java.lang.Iterable<T2>() { public Iterator<T2> iterator() { final Iterator<T> rawIterator = raw.iterator(); return new Iterator<T2>() { public boolean hasNext() { return rawIterator.hasNext(); } public T2 next() { return mapper.map(rawIterator.next()); } public void remove() { rawIterator.remove(); } }; } }); } public <T2> T2 inject(T2 initial, final Injector<T, T2> injector) { T2 cur = initial; for (T x : raw) cur = injector.inject(x, cur); return cur; } } }
こう書ける
ArrayList<Integer> arr = new ArrayList<Integer>(); arr.add(1); arr.add(2); arr.add(3); int squared_sum = Functional.from(arr).map( new Functional.Mapper<Integer, Integer>() { public Integer map(Integer n) { return n * n; } }).inject(0, new Functional.Injector<Integer, Integer>() { public Integer inject(Integer x, Integer a) { return x + a; }; }); System.out.println(squared_sum);
ワハハ!長すぎる!!アホか!!!
もう開き直ることにする
System.out.println(Functional.from(arr).map("$x*$x").inject(0, "$x+$a"));
文字列最強!大勝利ですね!!!
実装はまあこんなかんじ。エンジン初期化のせいで100倍くらい実行速度が遅くなった感が……
private static final ScriptEngineManager scriptEngineManager=new ScriptEngineManager(); private static ScriptEngine rubyEngine; static { rubyEngine=scriptEngineManager.getEngineByName("jruby"); } public <T2> Functional.Iterable<T2> map(final String expression) { return map("x",expression); } public <T2> Functional.Iterable<T2> map(final String varName,final String expression) { final ScriptContext context=rubyEngine.getContext(); return map(new Mapper<T, T2>() { @SuppressWarnings("unchecked") public T2 map(T x) { context.setAttribute(varName, x, ScriptContext.ENGINE_SCOPE); try { return (T2)rubyEngine.eval(expression,context); } catch(ScriptException e) { throw new RuntimeException(e); } } }); } public <T2> T2 inject(T2 initial,final String expression) { return inject(initial,"x","a",expression); } public <T2> T2 inject(T2 initial,final String varIn, final String varOut, final String expression) { final ScriptContext context=rubyEngine.getContext(); return inject(initial, new Injector<T, T2>() { @SuppressWarnings("unchecked") public T2 inject(T x, T2 a) { context.setAttribute(varIn, x, ScriptContext.ENGINE_SCOPE); context.setAttribute(varOut, a, ScriptContext.ENGINE_SCOPE); try { return (T2)rubyEngine.eval(expression,context); } catch(ScriptException e) { throw new RuntimeException(e); } } }); }