001: // ============================================================================
002: // $Id: BinaryFunctor.java,v 1.18 2006/11/30 05:03:42 davidahall Exp $
003: // Copyright (c) 2002-2005 David A. Hall
004: // ============================================================================
005: // The contents of this file are subject to the Common Development and
006: // Distribution License (CDDL), Version 1.0 (the License); you may not use this
007: // file except in compliance with the License. You should have received a copy
008: // of the the License along with this file: if not, a copy of the License is
009: // available from Sun Microsystems, Inc.
010: //
011: // http://www.sun.com/cddl/cddl.html
012: //
013: // From time to time, the license steward (initially Sun Microsystems, Inc.) may
014: // publish revised and/or new versions of the License. You may not use,
015: // distribute, or otherwise make this file available under subsequent versions
016: // of the License.
017: //
018: // Alternatively, the contents of this file may be used under the terms of the
019: // GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
020: // case the provisions of the LGPL are applicable instead of those above. If you
021: // wish to allow use of your version of this file only under the terms of the
022: // LGPL, and not to allow others to use your version of this file under the
023: // terms of the CDDL, indicate your decision by deleting the provisions above
024: // and replace them with the notice and other provisions required by the LGPL.
025: // If you do not delete the provisions above, a recipient may use your version
026: // of this file under the terms of either the CDDL or the LGPL.
027: //
028: // This library is distributed in the hope that it will be useful,
029: // but WITHOUT ANY WARRANTY; without even the implied warranty of
030: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
031: // ============================================================================
032:
033: package net.sf.jga.fn;
034:
035: import java.io.Serializable;
036: import net.sf.jga.fn.adaptor.Bind1st;
037: import net.sf.jga.fn.adaptor.Bind2nd;
038: import net.sf.jga.fn.adaptor.ChainBinary;
039: import net.sf.jga.fn.adaptor.ComposeBinary;
040: import net.sf.jga.fn.adaptor.ComposeUnary;
041: import net.sf.jga.fn.adaptor.Distribute;
042: import net.sf.jga.fn.adaptor.Generate1st;
043: import net.sf.jga.fn.adaptor.Generate2nd;
044: import net.sf.jga.fn.adaptor.Identity;
045:
046: /**
047: * A Function Object that takes two arguments and returns a result. The two
048: * arguments are of type <code>T1</code> and <code>T2</code>, and
049: * the result is of type <code>R</code>
050: * <p>
051: * Copyright © 2002-2005 David A. Hall
052: *
053: * @author <a href="mailto:davidahall@users.sourceforge.net">David A. Hall</a>
054: **/
055:
056: abstract public class BinaryFunctor<T1, T2, R> extends Functor<R>
057: implements Serializable, Visitable {
058: /**
059: * Executes the function and returns the result.
060: */
061: abstract public R fn(T1 arg1, T2 arg2);
062:
063: /**
064: * Factory method that creates a UnaryFunctor that binds a constant value to
065: * this' first argument. Given argument <b>x</b>, the new functor will
066: * return <code>fn<sub>this</sub>(value, x)</code>
067: */
068: public UnaryFunctor<T2, R> bind1st(T1 value) {
069: return new Bind1st<T1, T2, R>(value, this );
070: }
071:
072: /**
073: * Factory method that creates a UnaryFunctor that binds a constant value to
074: * this' second argument. Given argument <b>x</b>, the new functor will
075: * return <code>fn<sub>this</sub>(x, value)</code>
076: */
077: public UnaryFunctor<T1, R> bind2nd(T2 value) {
078: return new Bind2nd<T1, T2, R>(value, this );
079: }
080:
081: /**
082: * Factory method that creates a Generator that binds constant values to
083: * this' arguments. The new generator will return
084: * <code>fn<sub>this</sub>(value1, value2)</code>
085: */
086: public Generator<R> bind(T1 value1, T2 value2) {
087: return bind1st(value1).bind(value2);
088: }
089:
090: /**
091: * FactoryMethod that creates a UnaryFunctor that passes its argument to
092: * each of the given functors, and uses the results as the arguments to this
093: * function. Given argument <b>x</b>, the new functor will return
094: * <code>fn<sub>this</sub>(g(x), h(x))</code>
095: */
096: public <F> UnaryFunctor<F, R> compose(UnaryFunctor<F, T1> g,
097: UnaryFunctor<F, T2> h) {
098: return new ComposeUnary<F, T1, T2, R>(g, h, this );
099: }
100:
101: /**
102: * FactoryMethod that creates a BinaryFunctor that passes its argument to
103: * each of the given functors, and uses the results as the arguments to this
104: * function. Given arguments <b>x</b> and <b>y</b>, the new functor will
105: * return <code>fn<sub>this</sub>(g(x,y), h(x,y))</code>
106: */
107: public <F1, F2> BinaryFunctor<F1, F2, R> compose(
108: BinaryFunctor<F1, F2, T1> g, BinaryFunctor<F1, F2, T2> h) {
109: return new ComposeBinary<F1, F2, T1, T2, R>(g, h, this );
110: }
111:
112: /**
113: * FactoryMethod that creates a BinaryFunctor that passes each of its two
114: * arguments to a pair of UnaryFunctors, then uses the results as arguments
115: * to this function. Given arguments <b>x</b> and <b>y</b>, the new functor
116: * will return <code>fn<sub>this</sub>(g(x), h(y))</code>. Note: this
117: * method cannot be called compose, as it is only distinct from the unary
118: * form of compose in its param types and its return type
119: */
120: public <F1, F2> BinaryFunctor<F1, F2, R> distribute(
121: UnaryFunctor<F1, T1> g, UnaryFunctor<F2, T2> h) {
122: return new Distribute<F1, F2, T1, T2, R>(g, h, this );
123: }
124:
125: /**
126: * FactoryMethod that converts this functor to a UnaryFunctor by using the
127: * given generator to produce the first argument. Given argument <b>y</b>,
128: * the new functor will return <code>fn<sub>this</sub>(gen(), y)</code>.
129: */
130:
131: public UnaryFunctor<T2, R> generate1st(Generator<T1> gen) {
132: return new Generate1st<T1, T2, R>(this , gen);
133: }
134:
135: /**
136: * FactoryMethod that converts this functor to a UnaryFunctor by using the
137: * given generator to produce the first argument. Given argument <b>x</b>,
138: * the new functor will return <code>fn<sub>this</sub>(x, gen())</code>.
139: */
140:
141: public UnaryFunctor<T1, R> generate2nd(Generator<T2> gen) {
142: return new Generate2nd<T1, T2, R>(this , gen);
143: }
144:
145: /**
146: * FactoryMethod that converts this functor to a Generator by using the two
147: * given generators to produce the arguments. The new functor will return
148: * <code>fn<sub>this</sub>(gen1(), gen2())</code>.
149: */
150:
151: public Generator<R> generate(Generator<T1> gen1, Generator<T2> gen2) {
152: return generate1st(gen1).generate(gen2);
153: }
154:
155: // -----------------
156: // Functor interface
157: // -----------------
158:
159: public R eval(Object... args) {
160: // @SuppressWarnings
161: // This generates two unchecked cast warnings: we're crossing the line from
162: // unsafe rawform code to typesafe generic code. This interface is known
163: // to be unsafe, and documented to the user as such.
164: return fn((T1) args[0], (T2) args[1]);
165: }
166:
167: // -------------------
168: // Visitable interface
169: // -------------------
170:
171: /**
172: * No-op implementation of Visitable interface.
173: */
174: public void accept(Visitor v) {
175: }
176: }
|