Awesome
JKScope
Java scope functions inspired by Kotlin
Table of Contents
- Motivation
- How to use
- Docs
Motivation
Inspired by the Kotlin scope function I want to make my Java code more structured and readable.
How to use
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'
}
Docs
JKScope interface methods
You need to implement JKScope
interface to use these methods.
class MyObject implements JKScope<MyObject> { }
letIt
and also
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
and takeUnless
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
letOut
method performs given function block on this object and returns result.
Integer value = new MyObject().letOut(it -> it.getInt());
letOpt
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));
JKScope static methods
Import static methods you need or import them all at once.
import static com.plugatar.jkscope.JKScope.*;
run
, runCatching
and runRec
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();
}
});
with
, withInt
, withLong
, withDouble
and withResource
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
variations
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
and optNonNull
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
and lazyOfValue
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");
Opt
object
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
object
Lazy
represents a value with lazy initialization.
Lazy<String> lazy = lazy(() -> {
//...
return "value";
});
Lazy<String> lazyOfValue = lazyOfValue("value");
Unchecked functions
All presented functions allow you to not process checked exceptions.
public static void main(String[] args) {
URI uri = let(() -> new URI("abc"));
}
Examples
Collection initialization
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");
});
Argument in a method chain
new MyBuilder()
.setFirst("first")
.setSecond("second")
.setThird(let(() -> {
//...
return "third";
}))
.setFourth("fourth")
.build()
Nth Fibonacci number
int value = letIntRec(10, (n, func) -> {
if (n <= 1) {
return 1;
} else {
return n * func.apply(n - 1);
}
});
Method argument processing
public static String checkNonNullNonEmptyStr(String value) {
return opt(value)
.takeNonNull().throwIfEmpty(NullPointerException::new)
.takeUnless(String::isEmpty).throwIfEmpty(IllegalArgumentException::new)
.get();
}
Safe resources
class MyResource implements AutoCloseable {
//...
}
withResource(new MyResource(), it -> {
//...
});