int globalValue = 0;
// No Referential Transparency
int rq(int x) {
globalValue++;
return x + globalValue;
}
//Referential Transparency
int rt(int x) {
return x + 1;
}
// No Referential Transparency
Math.random();
//Referential Transparency
Math.max(5, 42);
public List<Integer> unmodifiableListJdk8() {
List<Integer> jdkList = IntStream.range(0,20)
.boxed()
.collect(Collectors.toList());
return Collections.unmodifiableList(jdkList);
}
@Test
public void should_verify_behaviour_of_jdk_8_unmodifiable_list() throws Exception {
List<Integer> unmodifiableList = this.examples.unmodifiableListJdk8();
unmodifiableList.add(21);
assertThat(unmodifiableList).hasSize(21);
}
public java.util.List<Address> filterInvalidAddressFromRouenJdk8() {
return this.usersJdk8.stream()
.filter(User::isInvalidAddressFromRouen)
.map(User::getAddress)
.collect(Collectors.toList());
}
public List<Address> filterInvalidAddressFromRouenVavr() {
return this.usersVavr
.filter(User::isInvalidAddressFromRouen)
.map(User::getAddress);
}
java.util.List<User> filterUserWithValidEmail() {
return this.usersJdk8
.stream()
.filter(user -> {
try {
return user.isEmailValid();
} catch (InvalidFormatException e) {
return false;
}
})
.collect(Collectors.toList());
}
public List<User> filterUserWithValidAddressVavr() {
return this.usersVavr
.filter(user -> Try.of(() -> user
.isAddressValid())
.getOrElse(false));
}
Java 8
public java.util.stream.Stream<String> mapUserToLowerCaseUserNameWithJdk8Steam() {
java.util.stream.Stream<User> userNameStream = java.util.stream.Stream.of(generateUser(7), generateUser(15));
userNameStream.map(user -> user.getUserName()
.toUpperCase());
return userNameStream
.map(user -> user.getUserName().toLowerCase());
}
java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)
at java.util.stream.ReferencePipeline.<init>(ReferencePipeline.java:94)
at java.util.stream.ReferencePipeline$StatelessOp.<init>(ReferencePipeline.java:618)
at java.util.stream.ReferencePipeline$3.<init>(ReferencePipeline.java:187)
at java.util.stream.ReferencePipeline.map(ReferencePipeline.java:186)
Vavr
public Stream<String> mapUserToLowerCaseUserNameWithVavrStream() {
Stream<User> userNameStream = Stream.of(generateUser(7), generateUser(15));
userNameStream.map(user -> user.getUserName()
.toUpperCase());
return userNameStream
.map(user -> user.getUserName().toLowerCase());
}
public java.util.Map<String, User> filterMapOfUserWithPredicateJdk8(Predicate<User> predicate) {
java.util.Map<String, User> usersMap = this.usersToMapJdk8();
return usersMap.entrySet().stream()
.filter(entry -> predicate.test(entry.getValue()))
.collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));
}
public Map<String, User> filterMapOfUserWithPredicateVavr(Predicate<User> predicate) {
Map<String, User> userMap = this.usersToMap();
return userMap
.filter(tuple -> predicate.test(tuple._2));
}
public Optional<Address> optionalOfUserAddress(String userName) {
if( !this.usersJdk8.containsKey(userName)) {
return Optional.empty();
}
return Optional.of(this.usersJdk8.get(userName).getAddress());
}
public Optional<Address> optionalOfNullUsageForUserAddress(String userName) {
return Optional.ofNullable(this.usersJdk8.get(userName))
.map(user -> user.getAddress());
}
public Option<Address> optionOfUserAddress(String userName) {
return this.usersVavr.get(userName)
.map(user -> user.getAddress());
}
/* Because Map.get(key) return an Option in Vavr
Option<V>get(K var1);
*/
public Try tryOfUserAddress(String userName) {
return Try.of(() -> this.usersVavr.get(userName)
.get().getAddressIfValid());
}
public Either<String, User> eitherOfUser(String userName) {
return this.usersVavr.get(userName)
.toRight("Not Found");
}
In fact Vavr functional interfaces areVavr documentation
Java 8 functional interfaces on steroids
Function1<User, String> lastName = User::getLastName;
Function1<String, String> toUpperCase = String::toUpperCase;
Function1<Option<User>, Option<String>> lastNameInUpperCase
= lastName.andThen(toUpperCase);
String userLastNameToUpperCase(String userName) {
return lastNameInUpperCase
.apply(usersJavaslang.get(userName))
.getOrElse("User Not Found");
}
Function1<Option<User>, Address> getAddressWithSideEffect
= user -> user.get().getAddress();
Function1<Option<User>, Option<Address>> safeGetAddress
= Function1.lift(getAddressWithSideEffect);
Address sideEffectGetAddress(String userName) {
return getAddressWithSideEffect
.apply(usersJavaslang.get(userName));
}
Option<Address> safeGetAddress(String userName) {
return safeGetAddress
.apply(this.usersVavr.get(userName));
}
Function4 <Integer,Integer,Integer,Integer,Integer> sum
= (a, b, c, d ) -> a + b + c + d;
Function1<Integer, Integer> partialApplicationFunc
= sum.apply(1,2,3);
int partialApplication(int val) {
return partialApplicationFunc.apply(val);
}
Function1<Integer, Function1<Integer, Function1<Integer, Integer>>> curriedFunc
= sum.curried().apply(5);
int currying(int val1, int val2, int val3) {
return curriedFunc.apply(val1).apply(val2).apply(val3);
}
Function0<Double> memoizedRandom = Function0.of(Math::random).memoized();
double memoize() {
return memoizedRandom.apply();
}
@Test
void should_use_memoization_to_add() throws Exception {
double firstCall = this.examples.memoize();
assertThat(List.range(0, 20)
.map(val -> this.examples.memoize()))
.allMatch(val -> val == firstCall);
}
Case($(is(1)), "one")
Case($(isIn("-h", "--help")), ...)
Function0<Option<String>> usageDocumentation = () -> Option.of("usage: VavrDemo [options] \n-h, --help : Display command line help\n");
Function1<Option<String>, Option<String>> versionDocumentation = previous -> previous.map(prev -> prev + "-v, --version : Display version Information");
Function0<Option<String>> helpDocumentation = usageDocumentation.andThen(versionDocumentation);
Function2<Option<String>, Option<String>, Option<String>> invalidCommand = (previous, arg) -> previous.map(prev -> "Unable to parse command line option : " + arg.getOrElse("") +"\n" + prev);
public static void main( String[] args )
{
Option<String> arg = Array.of(args).headOption();
String commandDescription = API.Match(arg.getOrElse("")).of(
Case($(isIn("-h", "--help")), helpDocumentation.apply()),
Case($(isIn("-v", "--version")), versionDocumentation.apply(Option.none()) ),
Case($(), invalidCommand.apply(helpDocumentation.apply(), arg))
).getOrElse("Error when parsing argument");
System.out.println(commandDescription);
}
public List<Either<Address, Address>> patternMatchingList() {
List<User> users = this.usersVavr.map(tuple -> tuple._2).toList();
return users.map(user ->
Match(validateUser(Option.of(user))).of(
Case($Valid($()), validUser -> Either.right(validUser.getAddress())),
Case($Invalid($()), errorList -> Either.left(user.getAddress()))
));
}
@Test
public void should_l33t_string() throws Exception {
Arbitrary<String> leetCharEto3 = Arbitrary.string(Gen.frequency(
Tuple.of(1, Gen.choose('A','Z')),
Tuple.of(1, Gen.choose('a','z'))
))
.filter(s -> s.length() > 10)
.filter(s -> s.matches("\\w*[eE]+\\w*"));
Function1<String, String> transformETo3 =
s -> s.replaceAll("[eE]", "3");
CheckedFunction1<String, Boolean> checkTransformETo3 =
s -> transformETo3.apply(s)
.matches("\\w*[^eE]+\\w*")
&& transformETo3.apply(s).contains("3");
Property.def("Each e character must be replace by a 3")
.forAll(leetCharEto3)
.suchThat(checkTransformETo3)
.check()
.assertIsSatisfied();
}
Documentation: https://goo.gl/dMKKjN
Javadoc: https://goo.gl/PHQ81g