Java scope functions inspired by Kotlin
- Motivation
- How to use
- Docs
Inspired by the Kotlin scope function I want to make my Java code more structured and readable.
Java 8+ version required. The library has no dependencies. All you need is this (get the latest version here).
Maven:
<dependency>
<groupId>com.plugatar.jkscope</groupId>
<artifactId>jkscope</artifactId>
<version>2.3</version>
<scope>compile</scope>
</dependency>
Gradle:
dependencies {
implementation 'com.plugatar.jkscope:jkscope:2.3'
}
You need to implement JKScope
interface to use these methods.
class MyObject implements JKScope<MyObject> { }
Both methods are the same and differ in the name only. Methods perform the function block on this object and return this object.
MyDTO myDTO = new MyDTO().letIt(it -> {
it.setProperty("value");
it.setAnother("another value");
});
MyResource myResource = new MyResource().also(it -> it.init());
takeIf
method performs the function block on this object and returns Opt
monad of this object if the condition is
met, or it returns empty Opt
instance if the condition is not met. And takeUnless
method has reverse logic.
new MyObject().takeIf(it -> it.getInt() > 10).takeUnless(it -> it.getInt() > 20).letIt(it -> System.out.println(it));
letOut
method performs given function block on this object and returns result.
Integer value = new MyObject().letOut(it -> it.getInt());
letOpt
method performs given function block on this object and returns Opt
monad of result.
new MyObject().letOpt(it -> it.getInt()).takeIf(it -> it > 10).letIt(it -> System.out.println(it));
Import static methods you need or import them all at once.
import static com.plugatar.jkscope.JKScope.*;
run
just runs given function block, runCatching
runs ignore any Throwable, runRec
runs function block allowing
yourself to be called recursively.
run
method simply runs given function block, runCatching
runs ignore any thrown Throwable, runRec
runs function
block, allowing itself to be called recursively.
run(() -> {
System.out.println("Hi");
});
runCatching(() -> {
System.out.println("Hi");
});
runRec(func -> {
if (new Random().nextInt(0, 100) == 50) {
func.run();
}
});
These methods perform given function block on given values.
with(value, it -> {
System.out.println(value);
});
with(value1, value2, (v1, v2) -> {
System.out.println(v1);
System.out.println(v2);
});
withResource
method does the same thing, but with a AutoCloseable
resource and closes this resource.
let
, letInt
, letLong
and letDouble
returns result of function block.
String value = let(() -> {
//...
return "val";
});
let
, letInt
, letLong
and letDouble
methods can also receive a value, process it using a function block, and
return that value.
String value = let("val", it -> {
System.out.println(it);
});
letRec
, letIntRec
, letLongRec
and letDoubleRec
accept initial value and allow you to process it recursively
returning the result.
int value = letIntRec(10, (n, func) -> {
if (n <= 1) {
return 1;
} else {
return n * func.apply(n - 1);
}
});
letWith
, letIntWith
, letLongWith
, letDoubleWith
methods accept values and returning the result of function
block.
int value = letWith("42", it -> Integer.valueOf(it));
letWithResource
method does the same thing, but with a AutoCloseable
resource and closes this resource.
opt
returns Opt
instance of given value, optNonNull
returns Opt
instance of given value of given value or
empty Opt
instance if given value is null.
opt(value).takeNonNull().takeUnless(it -> it.isEmpty()).takeIf(it -> it.length() < 100).letIt(it -> System.out.println(it));
optNonNull(value).takeUnless(it -> it.isEmpty()).takeIf(it -> it.length() < 100).letIt(it -> System.out.println(it));
lazy
returns Lazy
instance with given initializer. lazyOfValue
returns Lazy
instance of given value.
Lazy<String> lazy = lazy(() -> {
//...
return "value";
});
Lazy<String> lazyOfValue = lazyOfValue("value");
The Opt
monad is similar in meaning to Java Optional
, but allows the null value.
Opt
monad contains some Optional
methods and scope functions methods.
String result = Opt.of(value).takeIf(it -> it.length() > 10).orElse("");
String result = Opt.of(value).takeNonNull().orElseGet(() -> "");
String result = Opt.of(value).takeIf(it -> it.length() > 10).orElseThrow(() -> new IllegalArgumentException());
Lazy
represents a value with lazy initialization.
Lazy<String> lazy = lazy(() -> {
//...
return "value";
});
Lazy<String> lazyOfValue = lazyOfValue("value");
All presented functions allow you to not process checked exceptions.
public static void main(String[] args) {
URI uri = let(() -> new URI("abc"));
}
Map<String, Integer> map = let(new HashMap<>(), it -> {
it.put("val1", 1);
it.put("val2", 2);
});
List<String> list = let(new ArrayList<>(), it -> {
it.add("val1");
it.add("val2");
});
new MyBuilder()
.setFirst("first")
.setSecond("second")
.setThird(let(() -> {
//...
return "third";
}))
.setFourth("fourth")
.build()
int value = letIntRec(10, (n, func) -> {
if (n <= 1) {
return 1;
} else {
return n * func.apply(n - 1);
}
});
public static String checkNonNullNonEmptyStr(String value) {
return opt(value)
.takeNonNull().throwIfEmpty(NullPointerException::new)
.takeUnless(String::isEmpty).throwIfEmpty(IllegalArgumentException::new)
.get();
}
class MyResource implements AutoCloseable {
//...
}
withResource(new MyResource(), it -> {
//...
});