package net.varkhan.base.functor.curry; import net.varkhan.base.functor._; /** * <b></b>. * <p/> * * @author varkhan * @date 12/1/13 * @time 12:33 PM */ public interface Tuple<L, _T extends _> extends _<L,_T> { public L lvalue(); public _T _value(); public Object[] values(); public static class Value<L,_T extends _> implements Tuple<L,_T> { protected final Object[] values; public Value(_<L,? extends _T> t) { this.values = t.values(); } public Value(L l, Object... values) { this.values = uncurry(l, values); } protected Value(Object[] values) { this.values = values; } @SuppressWarnings("unchecked") public L lvalue() { return (L) values[0]; } @SuppressWarnings("unchecked") public _T _value() { return (values==null||values.length<=1)?null:(_T) new Value(rcurry(values)); } public Object[] values() { return values; } protected static <L> Object[] uncurry(L l, Object[] values) { if(values==null||values.length==0) return new Object[]{l}; Object[] v = new Object[1+values.length]; v[0] = l; System.arraycopy(values,0,v,1,values.length); return v; } @SuppressWarnings("unchecked") protected static <L> L lcurry(Object[] values) { if(values==null||values.length==0) return null; return (L) values[0]; } @SuppressWarnings("unchecked") protected static Object[] rcurry(Object[] values) { if(values==null||values.length<=1) return new Object[0]; Object[] v = new Object[values.length-1]; System.arraycopy(values,1,v,0,values.length-1); return v; } @Override public boolean equals(Object o) { if(this==o) return true; if(!(o instanceof Tuple)) return false; Tuple that=(Tuple) o; final int l = values.length; Object[] thisV = this.values(); Object[] thatV = that.values(); if (thatV.length!=l) return false; for (int i=0; i<l; i++) { Object thisO = thisV[i]; Object thatO = thatV[i]; if (!(thisO==null ? thatO==null : thisO.equals(thatO))) return false; } return true; } @Override public int hashCode() { if (values==null) return 0; int h = 1; for (Object v: values) h = 31*h + (v==null?0:v.hashCode()); return h; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append('('); boolean f = true; for(Object v: values) { if(f) f = false; else buf.append(','); buf.append(v); } buf.append(')'); return buf.toString(); } } }