001    package fj;
002    
003    import static fj.FW.$;
004    
005    /**
006     * A product-5.
007     *
008     * @version %build.number%<br>
009     *          <ul>
010     *          <li>$LastChangedRevision: 270 $</li>
011     *          <li>$LastChangedDate: 2009-07-28 14:06:27 +1000 (Tue, 28 Jul 2009) $</li>
012     *          </ul>
013     */
014    public abstract class P5<A, B, C, D, E> {
015      /**
016       * Access the first element of the product.
017       *
018       * @return The first element of the product.
019       */
020      public abstract A _1();
021    
022      /**
023       * Access the second element of the product.
024       *
025       * @return The second element of the product.
026       */
027      public abstract B _2();
028    
029      /**
030       * Access the third element of the product.
031       *
032       * @return The third element of the product.
033       */
034      public abstract C _3();
035    
036      /**
037       * Access the fourth element of the product.
038       *
039       * @return The fourth element of the product.
040       */
041      public abstract D _4();
042    
043      /**
044       * Access the fifth element of the product.
045       *
046       * @return The fifth element of the product.
047       */
048      public abstract E _5();
049    
050      /**
051       * Map the first element of the product.
052       *
053       * @param f The function to map with.
054       * @return A product with the given function applied.
055       */
056      public <X> P5<X, B, C, D, E> map1(final F<A, X> f) {
057        return new P5<X, B, C, D, E>() {
058          public X _1() {
059            return f.f(P5.this._1());
060          }
061    
062          public B _2() {
063            return P5.this._2();
064          }
065    
066          public C _3() {
067            return P5.this._3();
068          }
069    
070          public D _4() {
071            return P5.this._4();
072          }
073    
074          public E _5() {
075            return P5.this._5();
076          }
077        };
078      }
079    
080      /**
081       * Map the second element of the product.
082       *
083       * @param f The function to map with.
084       * @return A product with the given function applied.
085       */
086      public <X> P5<A, X, C, D, E> map2(final F<B, X> f) {
087        return new P5<A, X, C, D, E>() {
088          public A _1() {
089            return P5.this._1();
090          }
091    
092          public X _2() {
093            return f.f(P5.this._2());
094          }
095    
096          public C _3() {
097            return P5.this._3();
098          }
099    
100          public D _4() {
101            return P5.this._4();
102          }
103    
104          public E _5() {
105            return P5.this._5();
106          }
107        };
108      }
109    
110      /**
111       * Map the third element of the product.
112       *
113       * @param f The function to map with.
114       * @return A product with the given function applied.
115       */
116      public <X> P5<A, B, X, D, E> map3(final F<C, X> f) {
117        return new P5<A, B, X, D, E>() {
118          public A _1() {
119            return P5.this._1();
120          }
121    
122          public B _2() {
123            return P5.this._2();
124          }
125    
126          public X _3() {
127            return f.f(P5.this._3());
128          }
129    
130          public D _4() {
131            return P5.this._4();
132          }
133    
134          public E _5() {
135            return P5.this._5();
136          }
137        };
138      }
139    
140      /**
141       * Map the fourth element of the product.
142       *
143       * @param f The function to map with.
144       * @return A product with the given function applied.
145       */
146      public <X> P5<A, B, C, X, E> map4(final F<D, X> f) {
147        return new P5<A, B, C, X, E>() {
148          public A _1() {
149            return P5.this._1();
150          }
151    
152          public B _2() {
153            return P5.this._2();
154          }
155    
156          public C _3() {
157            return P5.this._3();
158          }
159    
160          public X _4() {
161            return f.f(P5.this._4());
162          }
163    
164          public E _5() {
165            return P5.this._5();
166          }
167        };
168      }
169    
170      /**
171       * Map the fifth element of the product.
172       *
173       * @param f The function to map with.
174       * @return A product with the given function applied.
175       */
176      public <X> P5<A, B, C, D, X> map5(final F<E, X> f) {
177        return new P5<A, B, C, D, X>() {
178          public A _1() {
179            return P5.this._1();
180          }
181    
182          public B _2() {
183            return P5.this._2();
184          }
185    
186          public C _3() {
187            return P5.this._3();
188          }
189    
190          public D _4() {
191            return P5.this._4();
192          }
193    
194          public X _5() {
195            return f.f(P5.this._5());
196          }
197        };
198      }
199    
200      /**
201       * Returns the 1-product projection over the first element.
202       *
203       * @return the 1-product projection over the first element.
204       */
205      public P1<A> _1_() {
206        return $(P5.<A, B, C, D, E>__1()).lazy().f(this);
207      }
208    
209      /**
210       * Returns the 1-product projection over the second element.
211       *
212       * @return the 1-product projection over the second element.
213       */
214      public P1<B> _2_() {
215        return $(P5.<A, B, C, D, E>__2()).lazy().f(this);
216      }
217    
218      /**
219       * Returns the 1-product projection over the third element.
220       *
221       * @return the 1-product projection over the third element.
222       */
223      public P1<C> _3_() {
224        return $(P5.<A, B, C, D, E>__3()).lazy().f(this);
225      }
226    
227      /**
228       * Returns the 1-product projection over the fourth element.
229       *
230       * @return the 1-product projection over the fourth element.
231       */
232      public P1<D> _4_() {
233        return $(P5.<A, B, C, D, E>__4()).lazy().f(this);
234      }
235    
236      /**
237       * Returns the 1-product projection over the fifth element.
238       *
239       * @return the 1-product projection over the fifth element.
240       */
241      public P1<E> _5_() {
242        return $(P5.<A, B, C, D, E>__5()).lazy().f(this);
243      }
244    
245      /**
246       * Provides a memoising P5 that remembers its values.
247       *
248       * @return A P5 that calls this P5 once for any given element and remembers the value for subsequent calls.
249       */
250      public P5<A, B, C, D, E> memo() {
251        return new P5<A, B, C, D, E>() {
252          private final P1<A> a = _1_().memo();
253          private final P1<B> b = _2_().memo();
254          private final P1<C> c = _3_().memo();
255          private final P1<D> d = _4_().memo();
256          private final P1<E> e = _5_().memo();
257    
258          public A _1() {
259            return a._1();
260          }
261    
262          public B _2() {
263            return b._1();
264          }
265    
266          public C _3() {
267            return c._1();
268          }
269    
270          public D _4() {
271            return d._1();
272          }
273    
274          public E _5() {
275            return e._1();
276          }
277        };
278      }
279    
280      /**
281       * Returns a function that returns the first element of a product.
282       *
283       * @return A function that returns the first element of a product.
284       */
285      public static <A, B, C, D, E> F<P5<A, B, C, D, E>, A> __1() {
286        return new F<P5<A, B, C, D, E>, A>() {
287          public A f(final P5<A, B, C, D, E> p) {
288            return p._1();
289          }
290        };
291      }
292    
293      /**
294       * Returns a function that returns the second element of a product.
295       *
296       * @return A function that returns the second element of a product.
297       */
298      public static <A, B, C, D, E> F<P5<A, B, C, D, E>, B> __2() {
299        return new F<P5<A, B, C, D, E>, B>() {
300          public B f(final P5<A, B, C, D, E> p) {
301            return p._2();
302          }
303        };
304      }
305    
306      /**
307       * Returns a function that returns the third element of a product.
308       *
309       * @return A function that returns the third element of a product.
310       */
311      public static <A, B, C, D, E> F<P5<A, B, C, D, E>, C> __3() {
312        return new F<P5<A, B, C, D, E>, C>() {
313          public C f(final P5<A, B, C, D, E> p) {
314            return p._3();
315          }
316        };
317      }
318    
319      /**
320       * Returns a function that returns the fourth element of a product.
321       *
322       * @return A function that returns the fourth element of a product.
323       */
324      public static <A, B, C, D, E> F<P5<A, B, C, D, E>, D> __4() {
325        return new F<P5<A, B, C, D, E>, D>() {
326          public D f(final P5<A, B, C, D, E> p) {
327            return p._4();
328          }
329        };
330      }
331    
332      /**
333       * Returns a function that returns the fifth element of a product.
334       *
335       * @return A function that returns the fifth element of a product.
336       */
337      public static <A, B, C, D, E> F<P5<A, B, C, D, E>, E> __5() {
338        return new F<P5<A, B, C, D, E>, E>() {
339          public E f(final P5<A, B, C, D, E> p) {
340            return p._5();
341          }
342        };
343      }
344    }