Skip to content

Instantly share code, notes, and snippets.

@janickr
Created October 11, 2014 21:42
Show Gist options
  • Save janickr/edeeb3179bf9bcacee38 to your computer and use it in GitHub Desktop.
Save janickr/edeeb3179bf9bcacee38 to your computer and use it in GitHub Desktop.
Transducers in java. An exercise based on http://phuu.net/2014/08/31/csp-and-transducers.html
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
public class Transducers {
static interface Reducer<Something, Input> extends BiFunction<Something, Input, Something> {}
static interface Transducer<Something, T, E> extends Function<Reducer<Something, E>, Reducer<Something, T>> {}
public static void main(String[] args) {
// I can do this
Transducer<List<Integer>, Integer, Integer> mapping = mapping(i -> i + i);
List<Integer> reduce1 = Arrays.asList(1, 2, 3).stream().reduce(new ArrayList<>(), mapping.apply(Transducers::add), Transducers::concat);
System.out.println("reduce1 = " + reduce1);
// and this
Collection<Integer> reduce2 = reduce(Arrays.asList(1, 2, 3), mapping.apply(Transducers::add), new ArrayList<>());
System.out.println("reduce2 = " + reduce2);
// and this
Collection<Integer> reduce3 = reduce(new Integer[]{1, 2, 3}, mapping.apply(Transducers::add), new ArrayList<>());
System.out.println("reduce3 = " + reduce3);
// But not this (compiler error)
ArrayList<Integer> reduce4 = Arrays.asList(1, 2, 3).stream().reduce(new ArrayList<>(), mapping(i -> i + i).apply(Transducers::add), Transducers::concat);
System.out.println("reduce4 = " + reduce4);
// nor this (compiler error)
Collection<Integer> reduce5 = reduce(Arrays.asList(1, 2, 3), mapping(i -> i + i).apply(Transducers::add), new ArrayList<>());
System.out.println("reduce5 = " + reduce2);
// nor this (compiler error)
Transducer<Collection<Integer>, Integer, Integer> combined = mapping(i -> i + i).andThen(filtering(i -> i > 4));
}
public static <Something, T, E> Transducer<Something, T, E> mapping(Function<T,E> transform) {
return (reducer) -> (list, input) -> reducer.apply(list, transform.apply(input));
}
public static <Something, E> Transducer<Something, E, E> filtering(Predicate<E> predicate) {
return (reducer) -> (list, input) -> predicate.test(input) ? reducer.apply(list, input) : list;
}
public static <E, C extends Collection<E>> C add(C collection, E element) {
collection.add(element);
return collection;
}
public static <T, C extends Collection<T>> C concat(C left, C right) {
left.addAll(right);
return left;
}
public static <T, E, OUT extends Collection<E>> OUT reduce(Iterable<T> input, Reducer<OUT, ? super T> reducer, OUT seed) {
OUT result = seed;
for (T t : input) {
result = reducer.apply(result, t);
}
return result;
}
public static <T, E, OUT extends Collection<E>> OUT reduce(T[] input, Reducer<OUT, ? super T> reducer, OUT seed) {
OUT result = seed;
for (T t : input) {
result = reducer.apply(result, t);
}
return result;
}
//
// functions from http://phuu.net/2014/08/31/csp-and-transducers.html
//
public static <T, E> Collection<E> map(Function<T,E> transform, Collection<T> list) {
return reduce(
list,
(result, input) -> add(result, transform.apply(input)),
new ArrayList<>()
);
}
public static <T> Collection<T> filter(Predicate<T> predicate, Collection<T> l) {
return reduce(l,
(r, t) -> predicate.test(t) ? add(r, t) : r ,
new ArrayList<>()
);
}
public static <T, E> Reducer<Collection<E>, T> mapper(Function<T,E> transform) {
return (list, input) -> add(list, transform.apply(input));
}
public static <E> Reducer<Collection<E>, E> filterer(Predicate<E> predicate) {
return (list, input) -> predicate.test(input) ? add(list, input) : list;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment