Created
October 11, 2014 21:42
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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