Commit a274309
Enable optional parameters using reduction
This PR introduces the ability to declare optional parameters in an Op's
**functional method** using the Optional annotation. The motivation
behind this implementation was to maintain from ImageJ Ops the ability
to declare optional parameters without the complexity of field
injection.
Once one parameter (or more) has been declared optional for some Op,
scijava ops will create a set of ReducedOpInfos for that Op; if an Op
has n optional parameters, we will then have n+1 OpInfos that delegate
to that Op (n of which being ReducedOpInfos). These ReducedOpInfos can
then be matched, just as any other OpInfo. **We maintain ImageJ Ops'
behavior of matching subsets of optional parameters in a left-to-right
manner**; this means that if there is an OpMethod:
public Double foo(Double a, @optional Double b, @optional Double c) {}
we can match this Op using:
* a
* a and b
* a, b, and c.
We do not allow the matching of a and c, as when b and c are the same
type, passing a Double would provide no indication whether that Double
should be assigned to b or c. To be deterministic we assume that
optional parameters are always left off **right to left**.
Using this paradigm, users can write a class Op with optional parameters
as
@plugin(type = Op.class, name = "foo")
public class OptionalArgClass implements BiFunction<Double, Double, Double> {
public Double apply( Double in1, @optional in2) {
if (in2 == null) in2 = <reasonable default>;
...
}
}
When this Op is called *without* the optional parameter, the
ReducedOpInfo will use Javassist to create a *wrapper* for
OptionalArgClass, passing null for each optional parameter that is
omitted in the matched ReducedOpInfo. *note that the Op author is then
responsible for null-checking any optional arguments*.
Using the OpBuilder syntax, this Op can then be called using *either*:
Double d1 = 1.0;
Double d2 = 2.0;
Double o = ops.op("foo").input(d1, d2).outType(Double.class).apply();
or:
Double d1 = 1.0;
Double o = ops.op("foo").input(d1).outType(Double.class).apply();
Ops written as methods can similarly be written with optional
parameters:
@OpMethod(names = "bar", type = BiFunction.class)
public Double barMethod(Double in1, @optional Double in2) {
if (in2 == null) in2 = <reasonable default>;
...
}
When writing an Op as a Field, there are two options.
One can write the Op as either an anonymous Class:
@OpField(names = "foobar")
public final BiFunction<Double, Double, Double> foobar = new BiFunction<> {
public Double apply( Double in1, @optional in2) {
if (in2 == null) in2 = <reasonable default>;
...
}
}
or, with the help of a specialized interface, using a lambda:
public interface BiFunctionWithOptional<I1, I2, I3, O> extends Functions.Arity3<I1, I2, I3, O> {
@OverRide
public O apply(I1 in1, I2 in2, @optional I3 in3);
}
@OpField(names = "baz")
public final BiFunctionWithOptional<Double, Double, Double, Double> baz = (in1, in2, in3) -> {
if (in3 == null) in3 = <reasonable default>;
...
};
To promote extensibility, each OpInfo is reduced using a InfoReducer
plugin. InfoReducers are designed to be able to reduce OpInfos backed by
one of a set of functional types (for example, a FunctionReducer should
reduce all Functions). For each functional type an InfoReducer can
reduce, it should be able to produce an OpInfo for any number of
optional parameters. So if, for example, an InfoReducer is able to
reduce a Functions.Arity3, it should be able to reduce that Arity3 into
a BiFunction, a Function, and a Producer. OpInfo reduction is performed
at plugin discovery time, and the Javassist wrapper is created when the
Op is matched.
Closes #14.
Signed-off-by: Curtis Rueden <ctrueden@wisc.edu>1 parent 25384ba commit a274309
File tree
42 files changed
+2201
-241
lines changed- scijava
- scijava-function
- src/main/java/org/scijava/function
- templates/main/java/org/scijava/function
- scijava-ops-api/src/main/java/org/scijava/ops/api/features
- scijava-ops-engine
- src
- main/java
- org/scijava/ops/engine
- adapt
- complexLift
- functional
- matcher/impl
- reduce
- struct
- test/java/org/scijava/ops/engine/reduce
- templates/main/java
- scijava-ops-spi/src/main/java/org/scijava/ops/spi
- scijava-struct/src/main/java/org/scijava/struct
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
42 files changed
+2201
-241
lines changedLines changed: 62 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
40 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
41 | 43 | | |
42 | | - | |
| 44 | + | |
| 45 | + | |
43 | 46 | | |
44 | 47 | | |
45 | 48 | | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
63 | 84 | | |
64 | 85 | | |
65 | 86 | | |
| |||
70 | 91 | | |
71 | 92 | | |
72 | 93 | | |
73 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
74 | 116 | | |
75 | 117 | | |
76 | 118 | | |
| |||
Lines changed: 57 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
38 | 40 | | |
39 | 41 | | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| 46 | + | |
43 | 47 | | |
| 48 | + | |
44 | 49 | | |
| 50 | + | |
45 | 51 | | |
| 52 | + | |
46 | 53 | | |
| 54 | + | |
47 | 55 | | |
| 56 | + | |
48 | 57 | | |
| 58 | + | |
49 | 59 | | |
| 60 | + | |
50 | 61 | | |
| 62 | + | |
51 | 63 | | |
| 64 | + | |
52 | 65 | | |
| 66 | + | |
53 | 67 | | |
| 68 | + | |
54 | 69 | | |
| 70 | + | |
55 | 71 | | |
| 72 | + | |
56 | 73 | | |
| 74 | + | |
57 | 75 | | |
| 76 | + | |
58 | 77 | | |
| 78 | + | |
59 | 79 | | |
| 80 | + | |
60 | 81 | | |
61 | 82 | | |
62 | 83 | | |
| |||
67 | 88 | | |
68 | 89 | | |
69 | 90 | | |
70 | | - | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
71 | 126 | | |
72 | 127 | | |
73 | 128 | | |
| |||
0 commit comments