001 package fj.data.vector; 002 003 import fj.F; 004 import fj.F2; 005 import static fj.Function.curry; 006 import static fj.P.p2; 007 import fj.P1; 008 import fj.P2; 009 import fj.data.Array; 010 import fj.data.List; 011 import fj.data.NonEmptyList; 012 import fj.data.Stream; 013 014 import java.util.Iterator; 015 016 /** 017 * A vector-2. 018 */ 019 public final class V2<A> implements Iterable<A> { 020 021 private final P2<A, A> inner; 022 023 private V2(final P2<A, A> inner) { 024 this.inner = inner; 025 } 026 027 /** 028 * Creates a vector-2 from a homogeneous product-2. 029 * 030 * @param p The product-2 from which to create a vector. 031 * @return A new vector-2. 032 */ 033 public static <A> V2<A> p(final P2<A, A> p) { 034 return new V2<A>(p); 035 } 036 037 /** 038 * Returns the first element of this vector. 039 * 040 * @return the first element of this vector. 041 */ 042 public A _1() { 043 return inner._1(); 044 } 045 046 /** 047 * Returns the second element of this vector. 048 * 049 * @return the second element of this vector. 050 */ 051 public A _2() { 052 return inner._2(); 053 } 054 055 /** 056 * A first-class function to get the first element of a vector. 057 * 058 * @return a function that gets the first element of a given vector. 059 */ 060 public static <A> F<V2<A>, A> __1() { 061 return new F<V2<A>, A>() { 062 public A f(final V2<A> v) { 063 return v._1(); 064 } 065 }; 066 } 067 068 /** 069 * A first-class function to get the second element of a vector. 070 * 071 * @return a function that gets the second element of a given vector. 072 */ 073 public static <A> F<V2<A>, A> __2() { 074 return new F<V2<A>, A>() { 075 public A f(final V2<A> v) { 076 return v._2(); 077 } 078 }; 079 } 080 081 /** 082 * Returns an iterator for the elements of this vector. 083 * 084 * @return an iterator for the elements of this vector. 085 */ 086 public Iterator<A> iterator() { 087 return toStream().iterator(); 088 } 089 090 /** 091 * Returns a homogeneous product-2 equivalent to this vector. 092 * 093 * @return a homogeneous product-2 equivalent to this vector. 094 */ 095 public P2<A, A> p() { 096 return inner; 097 } 098 099 /** 100 * Returns a nonempty list with the elements of this vector. 101 * 102 * @return a nonempty list with the elements of this vector. 103 */ 104 public NonEmptyList<A> toNonEmptyList() { 105 return NonEmptyList.nel(_1(), List.single(_2())); 106 } 107 108 /** 109 * Returns a stream of the elements of this vector. 110 * 111 * @return a stream of the elements of this vector. 112 */ 113 public Stream<A> toStream() { 114 return Stream.cons(_1(), new P1<Stream<A>>() { 115 public Stream<A> _1() { 116 return Stream.single(_2()); 117 } 118 }); 119 } 120 121 /** 122 * Returns a function that transforms a vector-2 to a stream of its elements. 123 * 124 * @return a function that transforms a vector-2 to a stream of its elements. 125 */ 126 public static <A> F<V2<A>, Stream<A>> toStream_() { 127 return new F<V2<A>, Stream<A>>() { 128 public Stream<A> f(final V2<A> v) { 129 return v.toStream(); 130 } 131 }; 132 } 133 134 /** 135 * Returns a function that transforms a vector-2 to the equivalent product-2. 136 * 137 * @return a function that transforms a vector-2 to the equivalent product-2. 138 */ 139 public static <A> F<V2<A>, P2<A, A>> p_() { 140 return new F<V2<A>, P2<A, A>>() { 141 public P2<A, A> f(final V2<A> v) { 142 return v.p(); 143 } 144 }; 145 } 146 147 /** 148 * Returns an array with the elements of this vector. 149 * 150 * @return an array with the elements of this vector. 151 */ 152 @SuppressWarnings("unchecked") 153 public Array<A> toArray() { 154 return Array.array(_1(), _2()); 155 } 156 157 /** 158 * Maps the given function across this vector. 159 * 160 * @param f The function to map across this vector. 161 * @return A new vector after the given function has been applied to each element. 162 */ 163 public <B> V2<B> map(final F<A, B> f) { 164 return p(inner.split(f, f)); 165 } 166 167 /** 168 * Performs function application within a vector (applicative functor pattern). 169 * 170 * @param vf The vector of functions to apply. 171 * @return A new vector after zipping the given vector of functions over this vector. 172 */ 173 public <B> V2<B> apply(final V2<F<A, B>> vf) { 174 return p(inner.split(vf._1(), vf._2())); 175 } 176 177 /** 178 * Zips this vector with the given vector using the given function to produce a new vector. 179 * 180 * @param bs The vector to zip this vector with. 181 * @param f The function to zip this vector and the given vector with. 182 * @return A new vector with the results of the function. 183 */ 184 public <B, C> V2<C> zipWith(final F<A, F<B, C>> f, final V2<B> bs) { 185 return bs.apply(map(f)); 186 } 187 188 /** 189 * Zips this vector with the given vector to produce a vector of pairs. 190 * 191 * @param bs The vector to zip this vector with. 192 * @return A new vector with a length the same as the shortest of this vector and the given 193 * vector. 194 */ 195 public <B> V2<P2<A, B>> zip(final V2<B> bs) { 196 final F<A, F<B, P2<A, B>>> __2 = p2(); 197 return zipWith(__2, bs); 198 } 199 200 /** 201 * Zips this vector with the given vector to produce a vector of vectors. 202 * 203 * @param bs The vector to zip this vector with. 204 * @return A new vector of vectors. 205 */ 206 public V2<V2<A>> vzip(final V2<A> bs) { 207 final F2<A, A, V2<A>> __2 = V.v2(); 208 return zipWith(curry(__2), bs); 209 } 210 211 /** 212 * Return the first element of this vector as a product-1. 213 * 214 * @return the first element of this vector as a product-1. 215 */ 216 public P1<A> head() { 217 return new P1<A>() { 218 public A _1() { 219 return V2.this._1(); 220 } 221 }; 222 } 223 224 }