Skip to content

Instantly share code, notes, and snippets.

@tomwhoiscontrary
Created April 5, 2023 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomwhoiscontrary/1d4799fb85b4890a96edd2c01f761b15 to your computer and use it in GitHub Desktop.
Save tomwhoiscontrary/1d4799fb85b4890a96edd2c01f761b15 to your computer and use it in GitHub Desktop.
Another go at transducers in Java, this time on top of collectors, although this is not quite right
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
@FunctionalInterface
interface Transducer<T, U> {
static <T, U> Transducer<T, U> mapping(Function<T, U> function) {
return new Transducer<>() {
@Override
public <R> Collector<T, ?, R> apply(Collector<U, ?, R> downstream) {
return Collectors.mapping(function, downstream);
}
};
}
static <T> Transducer<T, T> filtering(Predicate<T> predicate) {
return new Transducer<>() {
@Override
public <R> Collector<T, ?, R> apply(Collector<T, ?, R> downstream) {
return Collectors.filtering(predicate, downstream);
}
};
}
<R> Collector<T, ?, R> apply(Collector<U, ?, R> downstream);
default <V> Transducer<T, V> then(Transducer<U, V> second) {
return new Transducer<>() {
@Override
public <R> Collector<T, ?, R> apply(Collector<V, ?, R> downstream) {
return Transducer.this.apply(second.apply(downstream));
}
};
}
}
class TransducersTest {
@Test
void mappingOnce() {
Function<Integer, String> function = "!"::repeat;
Transducer<Integer, String> mappingTransducer = Transducer.mapping(function);
Collector<String, ?, List<String>> terminalCollector = Collectors.toList();
Collector<Integer, ?, List<String>> mappingCollector = mappingTransducer.apply(terminalCollector);
assertThat(Stream.of(1, 2, 3).collect(mappingCollector),
equalTo(List.of("!", "!!", "!!!")));
}
@Test
void mappingTwice() {
Function<String, Integer> firstFunction = String::length;
Function<Integer, String> secondFunction = "*"::repeat;
Transducer<String, Integer> firstMappingTransducer = Transducer.mapping(firstFunction);
Transducer<Integer, String> secondMappingTransducer = Transducer.mapping(secondFunction);
Collector<String, ?, List<String>> terminalCollector = Collectors.toList();
Collector<String, ?, List<String>> mappingCollector = firstMappingTransducer.apply(secondMappingTransducer.apply(terminalCollector));
assertThat(Stream.of("un", "deux", "trois").collect(mappingCollector),
equalTo(List.of("**", "****", "*****")));
}
@Test
void filtering() {
Predicate<Integer> predicate = n -> n % 2 == 0;
Transducer<Integer, Integer> filteringTransducer = Transducer.filtering(predicate);
Collector<Integer, ?, List<Integer>> terminalCollector = Collectors.toList();
Collector<Integer, ?, List<Integer>> filteringCollector = filteringTransducer.apply(terminalCollector);
assertThat(Stream.of(1, 2, 3, 4, 5).collect(filteringCollector),
equalTo(List.of(2, 4)));
}
@Test
void composing() {
Function<String, Integer> firstFunction = String::length;
Predicate<Integer> predicate = n -> n % 2 == 0;
Function<Integer, String> secondFunction = "*"::repeat;
Transducer<String, Integer> firstMappingTransducer = Transducer.mapping(firstFunction);
Transducer<Integer, Integer> filteringTransducer = Transducer.filtering(predicate);
Transducer<Integer, String> secondMappingTransducer = Transducer.mapping(secondFunction);
Collector<String, ?, List<String>> terminalCollector = Collectors.toList();
Collector<String, ?, List<String>> composedCollector = firstMappingTransducer.then(filteringTransducer).then(secondMappingTransducer).apply(terminalCollector);
assertThat(Stream.of("ox", "cow", "bull", "steer", "heifer").collect(composedCollector),
equalTo(List.of("**", "****", "******")));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment