object should not be changed after it is created. 2. No implicit state: Hidden/Implicit state should be avoided. In functional programming state is not eliminated, instead, it’s made visible and explicit
not change any state outside of its functional scope. I.e, A function should only return a value to the invoker and should not affect any external state. 2. Pure functions only: Functional code is idempotent. A function should return values only based on the arguments passed and should not affect(side-effect) or depend on global state. Such functions always produce the same result for the same arguments.
and local type inference with var keyword and with in lambda arguments var myList = new ArrayList<String>(); var out = mapForEach(list, it -> it.length());
and we can pass objects initialized inline as well public class LambdaTest { public static void main(String[] args) { var thread = new Thread(new Runnable() { @Override public void run() { System.out.println("Hello from thread"); } }); thread.run(); System.out.println("Hello from main"); } }
and we can pass objects initialized inline as well public class LambdaTest { public static void main(String[] args) { var thread = new Thread(new Runnable() { @Override public void run() -> { System.out.println("Hello from thread"); } }); thread.run(); System.out.println("Hello from main"); } }
and we can pass objects initialized inline as well public class LambdaTest { public static void main(String[] args) { var thread = new Thread(() -> { System.out.println("Hello from thread"); }); thread.run(); System.out.println("Hello from main"); } }
own stuff? @FunctionalInterface // this doesn't do anything it is just informative. public interface FnFactory<T, S> { // The interface defines the contract for the anonymous class S execute(T it); }
own stuff? // The method takes an array and an instance of FnFactory as arguments static <T, S> ArrayList<S> mapForEach(List<T> arr, FnFactory<T, S> fn) { var newArray = new ArrayList<S>(); // We are executing the method from the FnFactory instance arr.forEach(t -> newArray.add( fn.execute(t))); return newArray; }
own stuff? var out = mapForEach(list, new FnFactory<String, Object>() { @Override public Object execute(final String it) { return it.length(); } }); System.out.println(out); OR var out = mapForEach(list, it -> it.length()); System.out.println(out);
UnaryOperator - single arg and return of same types • BinaryOperator - two args and return of same types • Function - single arg and return of different types • Consumer - single arg and no return • Predicate - single arg and boolean return • Supplier - no args just a return
<T, S> ArrayList<S> mapForEach(List<T> arr, Function<T, S> fn) { var newArray = new ArrayList<S>(); // We are executing the method from the Function instance arr.forEach(t -> newArray.add(fn.apply(t))); return newArray; } var out = mapForEach(list, it -> it.length()); System.out.println(out);
and monad like stuff • java.util.Collections ◦ Sort, binarySearch, min, max • Java.util.stream (mostly pure functions) ◦ map, reduce, filter, find, forEach, flatMap and so on • Optional ◦ ifPresent, orElse, filter, map and so on • Anything that accepts anonymous classes
// this is a higher-order-function that returns // an instance of Function interface Function<Integer, Integer> add(final int x) { // this is a closure, i.e, a variable holding // an anonymous inner class instance of the Function interface // which uses variables from the outer scope return new Function<Integer, Integer>() { @Override public Integer apply(Integer y) { // variable x is obtained from the outer // scope of this method which is declared as final return x + y; } }; } OR Function<Integer, Integer> add(final int x) { return y -> x + y; }
is a lambda expression behaving as a closure UnaryOperator<Integer> add = t -> { System.out.println("executing add"); return t + t; }; // This is a lambda expression behaving as a closure UnaryOperator<Integer> multiply = t -> { System.out.println("executing multiply"); return t * t; }; // Lambda closures are passed instead of plain functions System.out.println(addOrMultiply(true, add, multiply, 4)); System.out.println(addOrMultiply(false, add, multiply, 4)); } // This is a higher-order-function static <T, R> R addOrMultiply( boolean add, Function<T, R> onAdd, Function<T, R> onMultiply, T t ) { // Java evaluates expressions on ?: // lazily hence only the required method is executed return (add ? onAdd.apply(t) : onMultiply.apply(t)); }