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 }