Java Project Reactor subscribeOn behavior for Mono chains - java

I am learning about project reactor and get confused on some questions regarding subscribeOn()
My blocking code looks like (say getA(), getB(), getC(A, B), getD(A, B), getE(C, D) are both time complex functions)
public E someMethod() {
A a = getA();
B b = getB();
C c = getC(a, b);
D d = getD(a, b);
return getE(c, d);
}
Now I want to change it into a unblocking implementation, I wrote
public E someMethodUnblocking() {
Mono<A> a = Mono.fromCallable(getA).subscribeOn(Schedulers.boundedElastic());
Mono<B> b = Mono.fromCallable(getB).subscribeOn(Schedulers.boundedElastic());
Mono<C> c = Mono.zip(a, b, (aa, bb) -> getC(aa,bb)).subscribeOn(Schedulers.boundedElastic());
Mono<D> d = Mono.zip(a, b, (aa, bb) -> getD(aa,bb)).subscribeOn(Schedulers.boundedElastic());
return Mono.zip(c, d, (cc, dd) -> getE(cc, dd)).block()
}
Does this look like the correct implementation? will there be a difference if I remove the subscribeOn() when generating Mono a and b?

Your implementation subscribes twice to the (cold) monos a and b - and will run your costly getA() and getB() methods two times.
To avoid that, you should cache() the first two monos.

Related

Remove independent if conditions

Refer below code structure which I want to refactor:
#Builder
#Value
class ReasonAndAction {
String reason;
String action;
}
ReasonAndAction decideReasonAndAction(Input input) {
if(condition1(input)) {
return reactionAndAction1;
}
if(condition2(input)) {
return reactionAndAction2;
}
if(condition3(input)) {
return reactionAndAction3;
}
return ReasonAndAction.builder()
.reason("default")
.action("default")
.build();
}
All the if conditions are independent and may have some default behavior (else case). There may be need to add more if conditions with next versions which will make code bit ugly.
I want to remove if conditions and abstract out in separate classes and execute independently rather sequential.
Expected Behaviour :
Dont Have all If conditions at same place
If 2 or more if conditions are satisfied at the same time , then return new ReasonAndAction object in decideReasonAndAction method . Example - action : DO_SOMETHING , reason : CONDITION_1_AND_CONDITION_2_MET
Basically , execute all if conditions independently and get the result of all if conditions and then take action and reason accordingly.
What Java design pattern can be used here(if any) for meaningful abstraction such that default behavior(else condition at the end) is also maintained?
Can somebody please explain with example/pseudocode?
Your question is very interesting. And you have one condition:
If 2 or more conditions are satisfied, there are two or more actions and two or more reasons.
In my view, it can be solved by delegating of checking these conditions before the execution of class. However, the class should be very simple.
So let us start. This is a bad design as if we want to add new operation, then we need to add new else condition. So by doing this, we violate open closed principle of SOLID.
public class Calculator
{
public int Exec(int a, int b, string operation)
{
if (operation == "+")
return a + b;
else if (operation == "-")
return a - b;
else if (operation == "/")
return a / b;
return a * b;
}
}
What can we do? We can create an interface and use dependency inversion principle of SOLID.
Our interface:
public interface IOperation
{
int Exec(int a, int b);
}
and class:
public class CalculatorWithDependencyInversionPrinciple
{
public int Exec(IOperation operation, int a, int b)
{
return operation.Exec(a, b);
}
}
and extensions:
public class SumOperation : IOperation
{
public int Exec(int a, int b)
{
return a + b;
}
}
And if you want to add new functionality, then you need to add new class with implemented Operation interface. So our class CalculatorWithDependencyInversionPrinciple is closed for modification, but it is open for extension.
And this is a strategy pattern in action.
And you can call it like this:
int result = new CalculatorWithDependencyInversionPrinciple()
.Exec(new SumOperation(), 1, 2);
Output will be: 3
So far so good, but we want to have different operators ("Reasons" in your task) and our code should be simple and testable. In addition, we will try to make that our classes will have just one single responsibility. Read more about Single Responsibility Principle of SOLID.
So this is our operators:
public enum Operator // Reason
{
Plus,
Minus,
Divide,
Multiply
}
And this is mapping between Operator and its Operation:
public class OperationToOperator
{
public Dictionary<Operator, IOperation> OperationByOperator =
new Dictionary<Operator, IOperation>
{
{ Operator.Plus, new SumOperation() },
{ Operator.Minus, new MinusOperation() },
{ Operator.Divide, new DivideOperation() },
{ Operator.Multiply, new MultiplyOperation() },
};
}
Our condition class:
public class Condition
{
public Operator Operator { get; private set; }
public int A { get; private set; }
public int B { get; private set; }
public Condition(Operator operato, int a, int b)
{
Operator = operato;
A = a;
B = b;
}
}
and code would be executed like this:
List<Condition> conditions = new List<Condition>
{
new Condition(Operator.Plus, 1, 2),
new Condition(Operator.Minus, 4, 3),
new Condition(Operator.Multiply, 5, 6),
new Condition(Operator.Divide, 8, 2),
};
OperationToOperator operationToOperator = new OperationToOperator();
CalculatorWithDependencyInversionPrinciple calculatorWithDependencyInversionPrinciple
= new CalculatorWithDependencyInversionPrinciple();
foreach (Condition condition in conditions)
Console.WriteLine
(
calculatorWithDependencyInversionPrinciple.Exec
(
operationToOperator.OperationByOperator[condition.Operator],
condition.A,
condition.B
)
);
So we've created simple classes that are testable and we used Strategy pattern.

Singleton created with enum type, problems with threads safety

Good day, I have created Singleton :
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
public enum Singleton {
FIRST_INSTANCE;
String[] scrabbleLetters = {
"a","a","a","a","a","a","a","a","a","b","b","b","b","b","b","b","b","b",
"c","c","c","c","c","c","c","c","c","d","d","d","d","d","d","d","d","d","d",
};
private LinkedList<String> letterList = new LinkedList<>(Arrays.asList(scrabbleLetters));
private Object lock = new Object();
private Singleton() {
Collections.shuffle(letterList);
}
public static Singleton getInstance() {
return FIRST_INSTANCE;
}
public LinkedList<String> getLetterList() {
synchronized (lock) {
return FIRST_INSTANCE.letterList;
}
}
public LinkedList<String> getTiles(int howManyTiles) {
synchronized (lock) {
LinkedList<String> tilesToSend = new LinkedList<>();
for(int i=0; i<= howManyTiles; i++) {
tilesToSend.add(FIRST_INSTANCE.letterList.remove(0));
}
return tilesToSend;
}
}
}
and I have tested it on threads safety with this example :
import java.util.LinkedList;
public class ScrabbleTest {
public static void main(String[] args) {
Runnable getTiles = () -> {
System.out.println("In thread : " +Thread.currentThread().getName());
Singleton newInstance = Singleton.getInstance();
System.out.println("Instance ID: " + System.identityHashCode(newInstance));
System.out.println(newInstance.getLetterList());
LinkedList<String> playerOneTiles = newInstance.getTiles(7);
System.out.println("Player : " + Thread.currentThread().getName() + playerOneTiles);
System.out.println("Got Tiles for " + Thread.currentThread().getName());
};
new Thread(getTiles, "First").start();
new Thread(getTiles, "Second").start();
}
}
After executing it 10 times , I was sure that there is no problem, but when I run it last time I received this stack trace :
In thread : Second
In thread : First
Instance ID: 1380197535
Instance ID: 1380197535
[d, d, b, c, b, b, a, d, c, d, a, d, c, a, a, d, c, a, a, b, d, b, b, a, b, c, a, d, c, a, c, b, c, c, b, d, d]
Player : First[d, d, b, c, b, b, a, d]
Got Tiles for First
Exception in thread "Second" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at java.util.AbstractCollection.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at ScrabbleTest.lambda$0(ScrabbleTest.java:10)
at java.lang.Thread.run(Unknown Source)
This exception happens quit rarely, about 1 time for 20 executions.
I have found that ConcurrentModificationException may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible. In the code I have a lock that should prevent this situations, there is the same lock for changing and retrieving the list for synchronized blocks. I don't even imagine why this happens.
CME doesn't have as much to do with concurrency as the name might make you think. The most common occurrence for CME is in a single threaded context. In this case however, the threading is involved too.
Your problem comes from tilesToSend.add(FIRST_INSTANCE.letterList.remove(0)); in which you're modifying the letterList, but it's being iterated at the same time by println. Synchronization won't help here, since you'd have to synchronize a lot larger blocks than what is realistically possible.
Easy solution here is to return a copy of the list in getLetterList() like
return new LinkedList<>(FIRST_INSTANCE.letterList);
This way the original list can be modified by remove() while println is iterating the copy.

"Double" composition with CompletableFuture

I'm trying to avoid nesting CompletableFuture when combining 2 independent ones with a BiFunction that returns a third one.
Currently, using thenCombine() does not cut it:
// What I have
public CompletableFuture<CompletableFuture<C>> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<CompletableFuture<C>> cFuture = aFuture.thenCombine(bFuture, this::makeSomeC);
return cFuture;
}
// What I want
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
// obv this method does not exist
CompletableFuture<C> c = aFuture.thenBicompose(bFuture, this::makeSomeC);
}
private CompletableFuture<A> makeSomeA() {...}
private CompletableFuture<B> makeSomeB() {...}
private CompletableFuture<C> makeSomeC(A a, B b) {...}
I'm basically trying to find a way that looks like haskell if there was a CompletableFuture monad:
doStuff :: CompletableFuture C
doStuff = do
a <- makeSomeA
b <- makeSomeB
makeSomeC a b
makeSomeA :: CompletableFuture A
makeSomeB :: CompletableFuture B
makeSomeC :: A -> B -> CompletableFuture C
I read somewhere that join() is the flatMap of Completable future, so I think I could use this method to do something like aFuture.thenCombine(bFuture, ((Function<CompletableFuture<C>,C>) CompletableFuture::join).compose(this::makeSomeC) but I'm not sure this is the proper/advised way to go. And I cannot say that this help readability in any way...
To me it looks like thenCompose is the direct equivalent of the Haskell Monad.bind.
thenCompose can be nested in the same way as Haskell monad bind, which is also the result of a do-expression in Haskell. Using that your problem can be solved like this:
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
return aFuture.thenCompose(a -> bFuture.thenCompose(b -> makeSomeC(a, b)));
}
Explanation of the types
This can be seen by inspecting the types of the functions.
Monad bind -- which is written >>= in Haskell -- has the following type:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
thenCompose in Java has the following signature:
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn)
The above converted to Haskell syntax, with an extra parameter as an explicit this, looks like this:
thenCompose :: CompletionStage T -> (T -> CompletionStage U) -> CompletionStage U
We can see that this has the same structure as the Haskell type. The difference is the names, and the fact Haskell's support for higher-kinded types is not exactly expressed by Java interfaces.
Note on the Haskell code in the question
But I am a bit puzzled by your Haskell code. To me it looks like your Haskell code is doing the following:
public CompletableFuture<C> doStuff() {
return makeSomeA().thenCompose(a -> makeSomeB().thenCompose(b -> makeSomeC(a, b)));
}
That is, waiting until the makeSomeA operation has completed before starting on makeSomeB. The Java code on the other hand starts the two operations in parallel, then waits for the result before starting on C. But maybe it is a laziness thing.
I guess the simplest solution is just to apply a thenCompose(identity()) afterwards:
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<CompletableFuture<C>> cFuture = aFuture.thenCombine(bFuture, this::makeSomeC);
return cFuture.thenCompose(Function.identity());
}
Alternatively, introduce a simple Pair class to combine the results of A and B and use thenCompose():
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<Pair<A, B>> cFuture = aFuture.thenCombine(bFuture, Pair::new);
return cFuture.thenCompose(p -> makeSomeC(p.a, p.b));
}
private static class Pair<A, B> {
A a;
B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
}
And a third alternative without Pair:
public CompletableFuture<C> doStuff() {
CompletableFuture<A> aFuture = makeSomeA();
CompletableFuture<B> bFuture = makeSomeB();
CompletableFuture<Void> cFuture = CompletableFuture.allOf(aFuture, bFuture);
return cFuture.thenCompose(__ -> makeSomeC(aFuture.join(), bFuture.join()));
}

Filtering with truth tables

Imagine a Person class with a boolean flag indicating whether or not the person is employable - set to false by default.
public class Person{
boolean employable = false;
...
}
Now imagine having some external boolean methods which act on Person objects. For example, consider static boolean methods in a utility class.
public class PersonUtil{
public static boolean ofWorkingAge(Person p){
if(p.getAge() > 16) return true;
return false;
}
...
}
Boolean static methods are in essence analogous to boolean valued functions i.e. predicates.
We can construct a 2^(#predicates)-by-#predicates truth table out of predicates. For example, given three predicates: ofWorkingAge, ofGoodCharacter, isQualified we can construct the following 8-by-3 truth table:
T T T
T T F
T F T
T F F
F T T
F T F
F F T
F F F
We now want to employ people with desirable qualities. Let + indicate that we wish to consider somebody employable (i.e. set their employability flag to true) and - the opposite.
T T T | +
T T F | +
T F T | +
T F F | -
F T T | +
F T F | -
F F T | -
F F F | -
Now imagine having a collection of Person objects. For each person we adjust their employability flag according to the three predicates. We also update a count (this forces us to use the entire truth table instead of just the positives), so that given 1,000 people we want to end up with something like:
T T T | + 100
T T F | + 200
T F T | + 50
T F F | - 450
F T T | + 50
F T F | - 50
F F T | - 50
F F F | - 50
Presumably this can be thought of as filtering with truth tables. Setting employability flags and updating counts is a rather contrived example but you can easily see how we might instead want to set and update much more complicated things.
QUESTION
Is there a way of elegantly doing this? I can think of two solutions:
Clunky solution
Have a giant hand coded if, else if, else chain.
if(ofWorkingAge && ofGoodCharacter && isQualified){
c1++;
p.setEmployable(true)
}
else if(ofWorkingAge && ofGoodCharacter && !isQualified){
c2++;
p.setEmployable(true)
}
...
else if(!ofWorkingAge && !ofGoodCharacter && isQualified){
c7++;
}
else{
c8++;
}
This is just bad.
Slightly smarter solution
Pass predicates (perhaps in an array) and a collection of sentences to a method. Let the method generate the corresponding truth table. Loop over the people, set their employability, and return an array of counts.
I can see how things could be done with functional interfaces. This SO answer is potentially relevant. You could change PrintCommand to IsQualified and pass callCommand a Person instead of a string. But this also seems kindah clunky because we'd then have to have a new interface file for every predicate we come up with.
Is there any other Java 8-ish way of doing this?
Let's start with the list of predicates you have:
List<Predicate<Person>> predicates = Arrays.<Predicate<Person>> asList(
PersonUtil::ofWorkingAge, PersonUtil::ofGoodCharacter,
PersonUtil::isQualified);
To track which predicate is true or false, let's attach names to them creating NamedPredicate class:
public static class NamedPredicate<T> implements Predicate<T> {
final Predicate<T> predicate;
final String name;
public NamedPredicate(Predicate<T> predicate, String name) {
this.predicate = predicate;
this.name = name;
}
#Override
public String toString() {
return name;
}
#Override
public boolean test(T t) {
return predicate.test(t);
}
}
(one may attach BitSet or something like this for efficiency, but String names are also fine).
Now we need to generate a truth table which is a new list of predicates having names like "T T F" and able to apply the given combination of source predicates, negated or not. This can be generated easily with a bit of functional programming magic:
Supplier<Stream<NamedPredicate<Person>>> truthTable
= predicates.stream() // start with plain predicates
.<Supplier<Stream<NamedPredicate<Person>>>>map(
// generate a supplier which creates a stream of
// true-predicate and false-predicate
p -> () -> Stream.of(
new NamedPredicate<>(p, "T"),
new NamedPredicate<>(p.negate(), "F")))
.reduce(
// reduce each pair of suppliers to the single supplier
// which produces a Cartesian product stream
(s1, s2) -> () -> s1.get().flatMap(np1 -> s2.get()
.map(np2 -> new NamedPredicate<>(np1.and(np2), np1+" "+np2))))
// no input predicates? Fine, produce empty stream then
.orElse(Stream::empty);
as truthTable is a Supplier<Stream>, you can reuse it as many times as you want. Also note that all the NamedPredicate objects are generated on the fly by demand, we don't store them anywhere. Let's try to use this supplier:
truthTable.get().forEach(System.out::println);
The output is:
T T T
T T F
T F T
T F F
F T T
F T F
F F T
F F F
Now you can classify the persons collection by the truth table, for example, in the following way:
Map<String,List<Person>> map = truthTable.get().collect(
Collectors.toMap(np -> np.toString(), // Key is string like "T T F"
// Value is the list of persons for which given combination is true
np -> persons.stream().filter(np).collect(Collectors.toList()),
// Merge function: actually should never happen;
// you may throw assertion error here instead
(a, b) -> a,
// Use LinkedHashMap to preserve an order
LinkedHashMap::new));
Now you can easily get the counts:
map.forEach((k, v) -> System.out.println(k+" | "+v.size()));
To update the employable field we need to know how the desired truth table is specified. Let it be the collection of truth strings like this:
Collection<String> desired = Arrays.asList("T T T", "T T F", "T F T", "F T T");
In this case you may use the previously generated map:
desired.stream()
.flatMap(k -> map.get(k).stream())
.forEach(person -> person.setEmployable(true));
Basically, a truth value is a single bit and you can always use an integer value of n bits to encode n truth value. Then, interpreting the integer value as a number allows you to associate values with the combination of truth values using a linear table.
So using an int a encoded truth value/ table index, a generic truth table class may look like this:
public class TruthTable<O,V> {
final List<? extends Predicate<? super O>> predicates;
final ArrayList<V> values;
#SafeVarargs
public TruthTable(Predicate<? super O>... predicates) {
int size=predicates.length;
if(size==0 || size>31) throw new UnsupportedOperationException();
this.predicates=Arrays.stream(predicates)
.map(Objects::requireNonNull).collect(Collectors.toList());
values=new ArrayList<>(Collections.nCopies(1<<size, null));
}
public V get(O testable) {
return values.get(index(testable, predicates));
}
public V get(boolean... constant) {
if(constant.length!=predicates.size())
throw new IllegalArgumentException();
return values.get(index(constant));
}
public V set(V value, boolean... constant) {
if(constant.length!=predicates.size())
throw new IllegalArgumentException();
return values.set(index(constant), value);
}
public static <T> int index(T object, List<? extends Predicate<? super T>> p) {
int size=p.size();
if(size==0 || size>31) throw new UnsupportedOperationException();
return IntStream.range(0, size).map(i->p.get(i).test(object)? 1<<i: 0)
.reduce((a,b) -> a|b).getAsInt();
}
public static <T> int index(boolean... values) {
int size=values.length;
if(size==0 || size>31) throw new UnsupportedOperationException();
return IntStream.range(0, size).map(i->values[i]? 1<<i: 0)
.reduce((a,b) -> a|b).getAsInt();
}
}
The key point is the calculation of the int index from truth values. There are two versions. First, calculate from explicit boolean values for initializing the table or querying its state, second, for an actual test object and the list of applicable predicates. Note that these two methods are factored out into public static methods so that they can be used for alternative table types, e.g. an array of primitive values. The only thing to do is to create a linear storage for 2ⁿ values when you have n predicates, e.g. new int[1<<n] and then using these index methods for determining the entry to access for given values or an actual test candidate.
Instances of the generic TruthTable can be used as follows:
TruthTable<Person,Integer> scoreTable=new TruthTable<>(
PersonUtil::ofWorkingAge, PersonUtil::ofGoodCharacter, PersonUtil::isQualified);
scoreTable.set(+100, true, true, true);
scoreTable.set(+200, true, true, false);
scoreTable.set(+50, true, false, true);
scoreTable.set(-450, true, false, false);
scoreTable.set(+50, false, true, true);
scoreTable.set(-50, false, true, false);
scoreTable.set(-50, false, false, true);
scoreTable.set(-50, false, false, false);
Person p = …
int score = scoreTable.get(p);
I'm not sure if this is what you're looking for, but you could use a bitwise operators on your variables..
if(ofWorkingAge && ofGoodCharacter && isQualified){
c1++;
p.setEmployable(true)
}
might become
int combined = 0b00000000;
combined |= ofWorkingAge ? 0b00000100 : 0b00000000;
combined |= ofGoodCharacter ? 0b00000010 : 0b00000000;
combined |= isQualified ? 0b00000001 : 0b00000000;
switch (combined){
case 0b00000111:
c1++;
p.setEmployable(true)
break;
case 0b00000110:
// etc
where the last bits represent ofWorkingAge/ofGoodCharacter/isQualified.

Collect arguments to apply to curried functions in Java/Scala

I would like to create a class in Java 8 which is able to recursively create an object which has a method that takes a function parameter based on the parameters I added.
For example, I would like to be able to do this:
new X().param(23).param("some String").param(someObject)
.apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
The apply method would then apply the collected parameters to the given function.
I feel this should be possible without reflection while maintaing type-safety, but I can't quite figure out how. A solution in Scala is also welcome, if I can translate it to Java 8. If it's not possible, I'll also accept an answer that explains why.
What I have so far is essentially this:
class ParamCmd<A,X> {
final A param;
public ParamCmd(A param) {
this.param = param;
}
public<B> ParamCmd<B, Function<A,X>> param(B b) {
return new ParamCmd<>(b);
}
public void apply(Function<A,X> f) {
// this part is unclear to me
}
public static void main(String[] args) {
new ParamCmd<Integer,String>(0).param("oops").param(new Object())
// the constructed function parameters are reversed relative to declaration
.apply((Object c) -> (String b) -> (Integer a) ->
"args were " + a + " " + b + " " + c
);
}
}
As noted in the code comments, my problems are keeping the function parameters in the order of the calls of param(), and actually applying the parameters.
For an unlimited amount of parameters, the only solution I could think of is with Heterogeneous Lists in Scala.
It is probably isn't feasible in Java as there is type level computation going on with path-dependant types.
Using Heterogeneous Lists and Path-Dependant types:
import scala.language.higherKinds
object Main extends App {
val builder1 = HCons(23, HCons("Hello", HNil))
val builder2 = HCons(42L, builder1)
val res1:String = builder1.apply(i => s => i + s)
val res2:String = builder2.apply(l => i => s => (i+l) + s)
println(res1) // 23Hello
println(res2) // 65Hello
}
sealed trait HList {
type F[Res]
def apply[Res]: F[Res] => Res
}
case class HCons[Head, HTail <: HList](head: Head, tail: HTail) extends HList {
type F[Res] = Head => (tail.type)#F[Res]
def apply[Res]: F[Res] => Res = f => tail.apply(f(head))
}
case object HNil extends HList {
type F[Res] = Res
def apply[Res]: F[Res] => Res = identity
}
This code prints:
23Hello
65Hello
The second, more limited way of doing this, but which might work with Java, is to create multiple classes for each function length, which returns the next sized function length class wrapping the value, up to some maximal length - See the Applicative Builder in Scalaz: "Scalaz Applicative Builder"
This doesn't answer your question. However, maybe it helps someone to find a solution, or to explain why it isn't possible in Java and/or Scala.
It can be done in C++, with an arbitrary number of parameters, and without losing type-safety. The call-side look as follows. Unfortunately, the lambda syntax in C++ is quite verbose.
bar{}.param(23).param("some String").param(4.2).apply(
[](int i) {
return [=](std::string s) {
return [=](double d) {
std::cout << i << ' ' << s << ' ' << d << '\n';
};
};
});
Following is the definition of foo and bar. The implementation is straight-forward. However, I doubt that it is possible to build something like this in Java, because the way type parameters work in Java. Generics in Java can only be used to avoid type casts, and that's not enough for this use case.
template <typename Param, typename Tail>
struct foo {
Param _param;
Tail _tail;
template <typename P>
auto param(P p) {
return foo<P, foo>{p, *this};
}
template <typename Function>
auto apply(Function function) {
return _tail.apply(function)(_param);
}
};
struct bar {
template <typename P>
auto param(P p) {
return foo<P, bar>{p, *this};
}
template <typename Function>
auto apply(Function function) {
return function;
}
};
Sorry I just could give some leads in Scala:
Perhaps it would help to have a look at http://www.scala-lang.org/api/2.10.4/index.html#scala.Function$
.apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
pretty much looks like Function.uncurried
param(23).param("some String").param(someObject)
could be implemented using a list for an accumulator if you don't care for Type safety. If you want to keep the Types you could use the HList out of Shapeless https://github.com/milessabin/shapeless which comes with a handy tuppled method.
Implementation of param():
import shapeless._
import HList._
import syntax.std.traversable._
class Method(val l : HList = HNil) {
def param(p: Any) = new Method( p :: l )
}
Example
scala> val m = new Method().param(1).param("test")
m: Method = Method#1130ad00
scala> m.l
res8: shapeless.HList = test :: 1 :: HNil

Categories