The selector pattern
Sam Pullara
spullara at gmail.com
Tue Jan 28 09:23:21 PST 2014
It would be great if we posted code to the list with gist. Maybe in addition to the email so it is easier to read :) Sam
---Sent from Boxer | http://getboxer.com
Tried to create an implementation (renamed Cell because Picolisp calls it
Cell) off the top of my head:
@FunctionalInterface
public interface FunctionalField<FIELD extends Enum<?>> {
public Object untypedField(FIELD field);
@SuppressWarnings("unchecked")
public default <VALUE> VALUE field(FIELD field) {
return (VALUE) untypedField(field);
}
public static <FIELD extends Enum<FIELD>> Object
throwOnUndefinedField(FIELD field) throws Error {
throw new InternalError(field + " is undefined");
}
}
//==============================================================================================//
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
@FunctionalInterface
public interface Cell<ELEMENT> {
public <VALUE> VALUE select(BiFunction<? super ELEMENT, Cell<ELEMENT>, ?
extends VALUE> cons, Supplier<? extends VALUE> nil);
public static <ELEMENT, VALUE> VALUE nil(BiFunction<? super ELEMENT,
Cell<ELEMENT>, ? extends VALUE> cons,
Supplier<? extends VALUE> nil) {
return nil.get();
}
public default int size() {
return select(
(element, next) -> 1 + next.size(),
() -> 0
);
}
public default Cell<ELEMENT> first(int size) {
return Optional.of(size)
.<Cell<ELEMENT>>map(s -> select(
(element, next) -> s == 0
? nil()
: cons(element, next.first(s - 1))
,
Cell::nil
))
.orElseThrow(IllegalArgumentException::new)
;
}
public default <ELEMENT2> Cell<ELEMENT2> map(Function<? super ELEMENT, ?
extends ELEMENT2> mapper) {
return select(
(element, next) -> Cell.cons(mapper.apply(element), next.map(mapper)),
Cell::nil
);
}
public default <ELEMENT2> Cell<ELEMENT2> flatMap(Function<? super
ELEMENT, Cell<ELEMENT2>> mapper) {
return select(
(element, next) -> mapper
.apply(element)
.select(
Cell::cons,
() -> next.flatMap(mapper)
)
,
Cell::nil
);
}
public interface Cons<ELEMENT> {
public ELEMENT element();
public Cell<ELEMENT> next();
public default <VALUE> VALUE cons(BiFunction<? super ELEMENT,
Cell<ELEMENT>, ? extends VALUE> cons, Supplier<? extends VALUE> nil) {
return cons.apply(element(), next());
}
public static <ELEMENT> Cons<ELEMENT> new_(ELEMENT element,
Cell<ELEMENT> next) {
return $.$Cons.new_(element, next);
}
public enum $ {
;
@FunctionalInterface
private interface $Cons<ELEMENT> extends Cons<ELEMENT>,
FunctionalField<$Cons.Field> {
public enum Field {
element,
next
}
@Override
public default ELEMENT element() {
return field(Field.element);
}
public default Cell<ELEMENT> next() {
return field(Field.next);
}
public static <ELEMENT> $Cons<ELEMENT> new_(ELEMENT element,
Cell<ELEMENT> next) {
return field -> {
switch (field) {
case element: return element;
case next: return next;
default: return FunctionalField.throwOnUndefinedField(field);
}
};
}
}
}
}
public static <ELEMENT> Cell<ELEMENT> nil() {
return Cell::nil;
}
public static <ELEMENT> Cell<ELEMENT> cons(ELEMENT element, Cell<ELEMENT>
next) {
Objects.requireNonNull(element);
Objects.requireNonNull(next);
return Cons.new_(element, next)::cons;
}
public static void main(String... arguments) {
System.out.println(nil() == nil()); // true
Cell<Integer> cell =
cons(1, cons(2, cons(3, nil())))
;
System.out.println(cell.size() == 3); // true
System.out.println(cell.first(2).size() == 2); // true
}
}
Samuel Dennis R. Borlongan
On Tue, Jan 28, 2014 at 6:35 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> I've found a 'good' use case of why not allowing a lambda to implement a
> functional interface with a generic method is a little sad.
> http://forax.github.io/2014-01-27-8650156-the_selector_pattern.html
>
> cheers,
> Rémi
>
>
>
More information about the lambda-dev
mailing list