001 package fj.data.vector; 002 003 import fj.F; 004 import fj.F2; 005 import fj.P1; 006 import fj.P2; 007 import fj.P3; 008 import fj.P4; 009 import static fj.Function.curry; 010 import static fj.P.p2; 011 import fj.data.Array; 012 import fj.data.NonEmptyList; 013 import fj.data.Stream; 014 015 import java.util.Iterator; 016 017 /** 018 * A vector-4. 019 */ 020 public final class V4<A> implements Iterable<A> { 021 022 private final V3<A> tail; 023 private final P1<A> head; 024 025 private V4(final P1<A> head, final V3<A> tail) { 026 this.head = head; 027 this.tail = tail; 028 } 029 030 /** 031 * Creates a vector-4 from a homogeneous product-4. 032 * 033 * @param p The product-4 from which to create a vector. 034 * @return A new vector-4. 035 */ 036 public static <A> V4<A> p(final P4<A, A, A, A> p) { 037 return new V4<A>(new P1<A>() { 038 public A _1() { 039 return p._1(); 040 } 041 }, V3.p(new P3<A, A, A>() { 042 public A _1() { 043 return p._2(); 044 } 045 046 public A _2() { 047 return p._3(); 048 } 049 050 public A _3() { 051 return p._4(); 052 } 053 })); 054 } 055 056 /** 057 * Creates a vector-4 from a head and a tail. 058 * 059 * @param head The value to put as the first element of the vector. 060 * @param tail The vector representing all but the first element of the new vector. 061 * @return The new vector. 062 */ 063 public static <A> V4<A> cons(final P1<A> head, final V3<A> tail) { 064 return new V4<A>(head, tail); 065 } 066 067 /** 068 * Returns the first element of this vector. 069 * 070 * @return the first element of this vector. 071 */ 072 public A _1() { 073 return head._1(); 074 } 075 076 /** 077 * Returns the second element of this vector. 078 * 079 * @return the second element of this vector. 080 */ 081 public A _2() { 082 return tail._1(); 083 } 084 085 /** 086 * Returns the third element of this vector. 087 * 088 * @return the third element of this vector. 089 */ 090 public A _3() { 091 return tail._2(); 092 } 093 094 /** 095 * Returns the fourth element of this vector. 096 * 097 * @return the fourth element of this vector. 098 */ 099 public A _4() { 100 return tail._3(); 101 } 102 103 /** 104 * Returns all but the first element of this vector, as a vector-3. 105 * 106 * @return all but the first element of this vector, as a vector-3. 107 */ 108 public V3<A> tail() { 109 return tail; 110 } 111 112 /** 113 * Returns the first element of this vector, as a product-1. 114 * 115 * @return the first element of this vector, as a product-1. 116 */ 117 public P1<A> head() { 118 return head; 119 } 120 121 /** 122 * Returns an iterator for the elements of this vector. 123 * 124 * @return an iterator for the elements of this vector. 125 */ 126 public Iterator<A> iterator() { 127 return toStream().iterator(); 128 } 129 130 /** 131 * Returns a homogeneous product-4 equivalent to this vector. 132 * 133 * @return a homogeneous product-4 equivalent to this vector. 134 */ 135 public P4<A, A, A, A> p() { 136 return new P4<A, A, A, A>() { 137 public A _1() { 138 return V4.this._1(); 139 } 140 141 public A _2() { 142 return V4.this._2(); 143 } 144 145 public A _3() { 146 return V4.this._3(); 147 } 148 149 public A _4() { 150 return V4.this._4(); 151 } 152 }; 153 } 154 155 /** 156 * Returns a nonempty list with the elements of this vector. 157 * 158 * @return a nonempty list with the elements of this vector. 159 */ 160 public NonEmptyList<A> toNonEmptyList() { 161 return NonEmptyList.nel(_1(), tail.toNonEmptyList().toList()); 162 } 163 164 /** 165 * Returns a stream of the elements of this vector. 166 * 167 * @return a stream of the elements of this vector. 168 */ 169 public Stream<A> toStream() { 170 return Stream.cons(head._1(), new P1<Stream<A>>() { 171 public Stream<A> _1() { 172 return tail.toStream(); 173 } 174 }); 175 } 176 177 /** 178 * Returns an array with the elements of this vector. 179 * 180 * @return an array with the elements of this vector. 181 */ 182 @SuppressWarnings("unchecked") 183 public Array<A> toArray() { 184 return Array.array(_1(), _2(), _3(), _4()); 185 } 186 187 /** 188 * Maps the given function across this vector. 189 * 190 * @param f The function to map across this vector. 191 * @return A new vector after the given function has been applied to each element. 192 */ 193 public <B> V4<B> map(final F<A, B> f) { 194 return new V4<B>(head.map(f), tail.map(f)); 195 } 196 197 /** 198 * Performs function application within a vector (applicative functor pattern). 199 * 200 * @param vf The vector of functions to apply. 201 * @return A new vector after zipping the given vector of functions over this vector. 202 */ 203 public <B> V4<B> apply(final V4<F<A, B>> vf) { 204 return new V4<B>(P1.<A, B>apply(head, vf.head()), tail.apply(vf.tail())); 205 } 206 207 /** 208 * Zips this vector with the given vector using the given function to produce a new vector. 209 * 210 * @param bs The vector to zip this vector with. 211 * @param f The function to zip this vector and the given vector with. 212 * @return A new vector with the results of the function. 213 */ 214 public <B, C> V4<C> zipWith(final F<A, F<B, C>> f, final V4<B> bs) { 215 return bs.apply(map(f)); 216 } 217 218 /** 219 * Zips this vector with the given vector to produce a vector of pairs. 220 * 221 * @param bs The vector to zip this vector with. 222 * @return A new vector with a length the same as the shortest of this vector and the given 223 * vector. 224 */ 225 public <B> V4<P2<A, B>> zip(final V4<B> bs) { 226 final F<A, F<B, P2<A, B>>> __2 = p2(); 227 return zipWith(__2, bs); 228 } 229 230 /** 231 * Zips this vector with the given vector to produce a vector of vectors. 232 * 233 * @param bs The vector to zip this vector with. 234 * @return A new vector of vectors. 235 */ 236 public V4<V2<A>> vzip(final V4<A> bs) { 237 final F2<A, A, V2<A>> __2 = V.v2(); 238 return zipWith(curry(__2), bs); 239 } 240 241 /** 242 * Returns a function that transforms a vector-4 to a stream of its elements. 243 * 244 * @return a function that transforms a vector-4 to a stream of its elements. 245 */ 246 public static <A> F<V4<A>, Stream<A>> toStream_() { 247 return new F<V4<A>, Stream<A>>() { 248 public Stream<A> f(final V4<A> v) { 249 return v.toStream(); 250 } 251 }; 252 } 253 254 /** 255 * Returns a function that transforms a vector-4 to the equivalent product-4. 256 * 257 * @return a function that transforms a vector-4 to the equivalent product-4. 258 */ 259 public static <A> F<V4<A>, P4<A, A, A, A>> p_() { 260 return new F<V4<A>, P4<A, A, A, A>>() { 261 public P4<A, A, A, A> f(final V4<A> v) { 262 return v.p(); 263 } 264 }; 265 } 266 267 /** 268 * A first-class function to get the first element of a vector. 269 * 270 * @return a function that gets the first element of a given vector. 271 */ 272 public static <A> F<V4<A>, A> __1() { 273 return new F<V4<A>, A>() { 274 public A f(final V4<A> v) { 275 return v._1(); 276 } 277 }; 278 } 279 280 /** 281 * A first-class function to get the second element of a vector. 282 * 283 * @return a function that gets the second element of a given vector. 284 */ 285 public static <A> F<V4<A>, A> __2() { 286 return new F<V4<A>, A>() { 287 public A f(final V4<A> v) { 288 return v._2(); 289 } 290 }; 291 } 292 293 /** 294 * A first-class function to get the third element of a vector. 295 * 296 * @return a function that gets the third element of a given vector. 297 */ 298 public static <A> F<V4<A>, A> __3() { 299 return new F<V4<A>, A>() { 300 public A f(final V4<A> v) { 301 return v._3(); 302 } 303 }; 304 } 305 306 /** 307 * A first-class function to get the third element of a vector. 308 * 309 * @return a function that gets the third element of a given vector. 310 */ 311 public static <A> F<V4<A>, A> __4() { 312 return new F<V4<A>, A>() { 313 public A f(final V4<A> v) { 314 return v._4(); 315 } 316 }; 317 } 318 }