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