001 /*
002 Galois, a framework to exploit amorphous data-parallelism in irregular
003 programs.
004
005 Copyright (C) 2010, The University of Texas at Austin. All rights reserved.
006 UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS SOFTWARE
007 AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR ANY
008 PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF PERFORMANCE, AND ANY
009 WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF DEALING OR USAGE OF TRADE.
010 NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH RESPECT TO THE USE OF THE
011 SOFTWARE OR DOCUMENTATION. Under no circumstances shall University be liable
012 for incidental, special, indirect, direct or consequential damages or loss of
013 profits, interruption of business, or related expenses which may arise from use
014 of Software or Documentation, including but not limited to those resulting from
015 defects in Software and/or Documentation, or loss or inaccuracy of data of any
016 kind.
017
018 File: FnIterable.java
019
020 */
021
022
023
024 package util.fn;
025
026 import java.util.ArrayList;
027 import java.util.Iterator;
028 import java.util.List;
029
030 import util.Pair;
031
032 /**
033 * Functional programming like sequences. This class provides map-like functionality.
034 *
035 *
036 * @param <T> type of elements of the sequence
037 */
038 public class FnIterable<T> implements Iterable<T> {
039 private final Iterable<T> it;
040
041 private FnIterable(Iterable<T> it) {
042 this.it = it;
043 }
044
045 /**
046 * Creates a new functional sequence from an {@link java.lang.Iterable} object
047 *
048 * @param <T> type of elements of the sequence
049 * @param it the iterable object
050 * @return a functional sequence view of the iterable object
051 */
052 public static <T> FnIterable<T> from(Iterable<T> it) {
053 return new FnIterable<T>(it);
054 }
055
056 /**
057 * Produces a sequence of pairs from two sequences.
058 * <pre>
059 * {a1, a2, a3, ...}.zip({b1, b2, b3, ...}) ==> {(a1, b1), (a2, b2), (a3, b3), ...}
060 * </pre>
061 *
062 * @param <U> type of elements of the argument sequence
063 * @param o argument sequence to zip with
064 * @return sequence of pairs combining this and argument sequence
065 */
066 public final <U> FnIterable<Pair<T, U>> zip(final FnIterable<U> o) {
067 return new FnIterable<Pair<T, U>>(new Iterable<Pair<T, U>>() {
068 @Override
069 public Iterator<Pair<T, U>> iterator() {
070 final Iterator<T> inner1 = it.iterator();
071 final Iterator<U> inner2 = o.iterator();
072 return new Iterator<Pair<T, U>>() {
073 @Override
074 public boolean hasNext() {
075 return inner1.hasNext() || inner2.hasNext();
076 }
077
078 @Override
079 public Pair<T, U> next() {
080 T o1 = inner1.hasNext() ? inner1.next() : null;
081 U o2 = inner2.hasNext() ? inner2.next() : null;
082 return new Pair<T, U>(o1, o2);
083 }
084
085 @Override
086 public void remove() {
087 throw new UnsupportedOperationException();
088 }
089 };
090 }
091 });
092 }
093
094 /**
095 * Maps function to sequence
096 * <pre>
097 * {a1, a2, a3, ...}.map(fn) ==> {fn(a1), fn(a2), fn(a3), ...}
098 * </pre>
099 *
100 * @param <U> type of elements in result sequence
101 * @param fn function from elements in this sequence to elements of result sequence
102 * @return a sequence of the return values of the function
103 */
104 public final <U> FnIterable<U> map(final Lambda<T, U> fn) {
105 return new FnIterable<U>(new Iterable<U>() {
106 @Override
107 public Iterator<U> iterator() {
108 final Iterator<T> inner = it.iterator();
109 return new Iterator<U>() {
110 @Override
111 public boolean hasNext() {
112 return inner.hasNext();
113 }
114
115 @Override
116 public U next() {
117 return fn.call(inner.next());
118 }
119
120 @Override
121 public void remove() {
122 throw new UnsupportedOperationException();
123 }
124 };
125 }
126 });
127 }
128
129 /**
130 * Reduces this sequence to a value.
131 * <pre>
132 * {}.reduce(fn, initial) ==> initial
133 * {a1, a2, a3, ...}.reduce(fn, initial) ==> fn(... fn(fn(fn(initial, a1), a2), a3) ...)
134 * </pre>
135 *
136 * @param <U> type of the resulting value
137 * @param fn function to reduce sequence
138 * @param initial initial value to pass reducing function
139 * @return resulting value from applying function over sequence
140 */
141 public final <U> U reduce(Lambda2<U, T, U> fn, U initial) {
142 for (T item : this) {
143 initial = fn.call(initial, item);
144 }
145 return initial;
146 }
147
148 /**
149 * @return a copy of this sequence as a list
150 */
151 public final List<T> toList() {
152 List<T> retval = new ArrayList<T>();
153 for (T item : this) {
154 retval.add(item);
155 }
156 return retval;
157 }
158
159 @Override
160 public Iterator<T> iterator() {
161 return it.iterator();
162 }
163 }