-
Notifications
You must be signed in to change notification settings - Fork 44
@Function
This annotation allows for a class to be automatically wrapped as an anonymous class, allowing the caller to pass it as an argument to a method that accepts a 'function'.
Encapsulates a method that returns a value, so its signature looks like this:
public R methodName(T1 t1, T2 t2, ..., Tn tn)
import lombok.ExtensionMethod;
import lombok.Function;
import java.util.Arrays;
import lombok.Functions.Function1;
import static lombok.Yield.yield;
@ExtensionMethod(Operations.class)
public class FunctionExample {
public static void main(String[] args) {
new String[] { "john", "james", "eddie" }.toList().filter(startsWith("j")).map(toUpperCase()).print('-');
// outputs "JOHN-JAMES"
}
@Function
private static boolean startsWith(String element, String _prefix) {
return element.startsWith(_prefix);
}
@Function
private static String toUpperCase(String element) {
return element.toUpperCase();
}
}
public class Operations {
public static <T> Iterable<T> filter(final Iterable<T> list, final Function1<T, Boolean> filter) {
for (T element : list) if (filter.apply(element)) yield(element);
}
public static <S, T> Iterable<T> map(final Iterable<S> list, final Function1<S, T> mapping) {
for (S element : list) yield(mapping.apply(element));
}
public static <T> Iterable<T> toList(final T[] array) {
return Arrays.asList(array);
}
public static <T> void print(final Iterable<T> list, final char delimiter) {
StringBuilder sb = new StringBuilder();
for (T element : list) {
sb.append(element.toString()).append(delimiter);
}
System.out.println(sb.length() > 0 ? sb.substring(0, sb.length() - 1) : "");
}
}
import java.util.Arrays;
import lombok.Functions.Function1;
public class Main {
public static void main(String[] args) {
Operations.print(Operations.map(Operations.filter(Operations.toList(new String[]{"john", "james", "eddie"}), artsWith("j")), toUpperCase()), '-');
// outputs "JOHN-JAMES"
}
@java.lang.SuppressWarnings("all")
private static lombok.Functions.Function1<String, java.lang.Boolean> startsWith(final String _prefix) {
return new lombok.Functions.Function1<String, java.lang.Boolean>(){
public java.lang.Boolean apply(final String element) {
return element.startsWith(_prefix);
}
};
}
@java.lang.SuppressWarnings("all")
private static lombok.Functions.Function1<String, String> toUpperCase() {
return new lombok.Functions.Function1<String, String>(){
public String apply(final String element) {
return element.toUpperCase();
}
};
}
}
public class Operations {
// same as above
// see also Yield.yield() - https://github.com/peichhorn/lombok-pg/wiki/Yield
// see also @ExtensionMethod - https://github.com/peichhorn/lombok-pg/wiki/%40ExtensionMethod
}
By default @Function
uses lombok.Functions
as template class. This means you need some lombok-pg classes at runtime. These runtime dependencies are located in lombok-pgs runtime artefact called lombok-pg-runtime.jar
.
As a benefit of using lombok.Functions
you get type information for free, which is accessible via getter methods such as: Class<?> getReturnType(), Class<?> getParameterType1() ... Class<?> getParameterTypeN()
on the function objects.
You may pass functions to other functions, creating higher order functions and monads. Furthermore closures are possible, just prefix a function's argument name with an underscore (_) to specify, as seen in the example above.
If you want to avoid having a runtime dependency to lombok-pg or just want to define you own template, use @Function(template=MyFunctionTemplate.class)
and make sure that MyFunctionTemplate satisfies the following conditions:
- The template class and any accessible (meaning public static) inner class qualifies as a possible template if they are abstract classes or interfaces that have only one abstract public method.
- The return type and the type arguments of the abstract method have to match the type arguments of the surrounding type.
- A template class must not define multiple templates for the same argument count.
Template Example: lombok.Functions (source)
Being able to specify a template class also allows you to use @Function
with other libraries such as google-guava @Function(template=com.google.common.base.Function.class)
.
I am not able to run @Action. If I provide Action1 implementation it works.
implementation private static Action1 println() { return new Action1() { public void apply(final Object o) { System.out.println(o); } };
pom : com.github.peichhorn lombok-pg 0.11.3
<dependency>
<groupId>com.github.peichhorn</groupId>
<artifactId>lombok-pg</artifactId>
<version>0.11.3</version>
<classifier>runtime</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>