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