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);
					}
				}
			});
		}