diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/Main.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/Main.java index 3e605fd..9ffe3b1 100644 --- a/functional-programming-java/src/main/java/org/gym/fp/fpjava/Main.java +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/Main.java @@ -1,11 +1,13 @@ package org.gym.fp.fpjava; +import org.gym.fp.fpjava.demo.AbstractControlStructureDemo; import org.gym.fp.fpjava.demo.FunctionDemo; public class Main { public static void main(String[] args) { FunctionDemo.run(); + AbstractControlStructureDemo.run(); } } diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/demo/AbstractControlStructureDemo.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/demo/AbstractControlStructureDemo.java new file mode 100644 index 0000000..8255ef0 --- /dev/null +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/demo/AbstractControlStructureDemo.java @@ -0,0 +1,49 @@ +package org.gym.fp.fpjava.demo; + +import org.gym.fp.fpjava.type.Effect; +import org.gym.fp.fpjava.type.Function; +import org.gym.fp.fpjava.type.Result; + +import java.util.regex.Pattern; + +import static org.gym.fp.fpjava.type.Case.match; +import static org.gym.fp.fpjava.type.Case.when; + +public class AbstractControlStructureDemo { + + public static void run() { + doEmailValidationDemo(); + } + + private static void doEmailValidationDemo() { + validate("this.is@my.email"); + validate(null); + validate(""); + validate("john.doe@acme.com"); + } + + private static void validate(String email) { + final EmailValidation validation = new EmailValidation(); + final Function> emailChecker = validation.emailChecker; + final Effect success = validation.success; + final Effect failure = validation.failure; + emailChecker.apply(email).bind(success, failure); + } +} + +class EmailValidation { + public final Pattern emailPattern = + Pattern.compile("^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$"); + + public final Effect success = + email -> System.out.println("Verification mail sent to " + email); + + public final Effect failure = + msg -> System.err.println("Error message logged: " + msg); + + public final Function> emailChecker = s -> match( + when(() -> Result.success(s)), + when(() -> s == null, () -> Result.failure("email must not be null")), + when(() -> s.length() == 0, () -> Result.failure("email must not be empty")), + when(() -> !emailPattern.matcher(s).matches(), () -> Result.failure("email " + s + " is invalid"))); +} diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Case.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Case.java new file mode 100644 index 0000000..205a288 --- /dev/null +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Case.java @@ -0,0 +1,31 @@ +package org.gym.fp.fpjava.type; + +public class Case extends Tuple, Supplier>> { + + public Case(Supplier booleanSupplier, Supplier> resultSupplier) { + super(booleanSupplier, resultSupplier); + } + + private static class DefaultCase extends Case { + + public DefaultCase(Supplier booleanSupplier, Supplier> resultSupplier) { + super(booleanSupplier, resultSupplier); + } + } + + public static Case when(Supplier condition, Supplier> value) { + return new Case<>(condition, value); + } + + public static DefaultCase when(Supplier> value) { + return new DefaultCase<>(() -> true, value); + } + + @SafeVarargs + public static Result match(DefaultCase defaultCase, Case... matchers) { + for (Case aCase : matchers) { + if (aCase._1.get()) return aCase._2.get(); + } + return defaultCase._2.get(); + } +} diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Effect.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Effect.java new file mode 100644 index 0000000..33c019c --- /dev/null +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Effect.java @@ -0,0 +1,5 @@ +package org.gym.fp.fpjava.type; + +public interface Effect { + void apply(T t); +} diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Executable.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Executable.java new file mode 100644 index 0000000..f177cb6 --- /dev/null +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Executable.java @@ -0,0 +1,5 @@ +package org.gym.fp.fpjava.type; + +public interface Executable { + void exec(); +} diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Result.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Result.java new file mode 100644 index 0000000..bdbbf2b --- /dev/null +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Result.java @@ -0,0 +1,43 @@ +package org.gym.fp.fpjava.type; + +public interface Result { + void bind(Effect success, Effect failure); + + static Result failure(String message) { + return new Failure<>(message); + } + + static Result success(T value) { + return new Success<>(value); + } + + class Success implements Result { + private final T value; + + public Success(T value) { + this.value = value; + } + + @Override + public void bind(Effect success, Effect failure) { + success.apply(value); + } + } + + class Failure implements Result { + private final String errorMessage; + + public Failure(String msg) { + this.errorMessage = msg; + } + + public String getMessage() { + return this.errorMessage; + } + + @Override + public void bind(Effect success, Effect failure) { + failure.apply(errorMessage); + } + } +} diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Supplier.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Supplier.java new file mode 100644 index 0000000..0d55039 --- /dev/null +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Supplier.java @@ -0,0 +1,5 @@ +package org.gym.fp.fpjava.type; + +public interface Supplier { + T get(); +} diff --git a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Tuple.java b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Tuple.java index 4aa36d1..79e767c 100644 --- a/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Tuple.java +++ b/functional-programming-java/src/main/java/org/gym/fp/fpjava/type/Tuple.java @@ -1,8 +1,8 @@ package org.gym.fp.fpjava.type; public class Tuple { - private final A _1; - private final B _2; + public final A _1; + public final B _2; public Tuple(A first, B second) { this._1 = first;