Say I have the following interface:
#FunctionalInterface
public interface First {
int fun(int a);
}
and also
#FunctionalInterface
public interface Second extends First {
default int fun(int a) { fun(a, a); }
int fun(int a, int b);
}
Then if I have a method somewhere that takes a First I can do, for example:
methodThatTakeFirst(val -> val + 1);
But I also want to be able to pass a Second, like:
methodThatTakeFirst((v1, v2) -> v2 * v2);
However this only works if I cast the lambda like this:
methodThatTakeFirst((Second) (v1, v2) -> v2 * v2);
My question is: is there a way to design this pattern without having to cast the lambdas to the subinterface? Or what would be the most elegant way to handle this scenarios?
You could overload methodThatTakeFirst, so that it also accepts an instance of Second as an argument, and delegate to methodThatTakeFirst(First first):
void methodThatTakeFirst(First first) {
// play with first
}
void methodThatTakeFirst(Second second) {
methodThatTakeFirst((First) second); // casting necessary
}
The cast is crucial, so that the compiler actually delegates to methodThatTakeFirst(First first), otherwise you'd end up with a StackOverflowError.
Whether this is a good design or not, I don't know, but I think it's outside the scope of this question.
Maybe just add another lambda?
void secondMethod(Second second) {
methodThatTakeFirst(x-> second.fun(x,x));
}
Related
I am studying JAVA functional interfaces and lambdas. I haven't studied other languages like Python, so I (still) don't get analogies to them (as indicated in other parts of the web).
I came across a similiar code:
interface Function<T,R> {
// T der Argumenttyp
// R der Ergebnistyp
R apply (T arg);
default <V> Function<T,V> andThen (
Function<? super R, ? extends V> after) {
return (T x) -> after.apply(apply(x));
}
}
class S implements Function<String,String> {
public String apply(String t) {return t+1;}
}
public class Test {
public static void main(String[] a) {
S f = new S();
Function<String,String> g = f.andThen(f);
System.out.println(g.andThen(g).apply("Hello")); //<--- The given code.
//System.out.println(g.apply(g.apply("Hello"))); //<--- What I would have done.
}
}
The commented line is what I would have used instead of the last line. Both run and deliver the same result, namely "Hello1111".
Question: Why does also the other option work?
The reason I am happy with my piece of code is that I am calling 'apply' 2 times: I have a Function-interface object 'g', I call apply on it and I get the String: "Hello11". I then treat this result as a parameter for a new 'apply' call and do the same. Key point: the 'andThen' method returns me an interface object on which I can call 'apply'.
The part of the given code which I do not understand is the following:
g = f.andThen(f);
g.andThen(g).apply("Hello")
I agree that g in the first line is a Function-interface object on which I can call 'apply'.
And I also agree that 'g.andThen(g)' is some Function-interface object on which I can call 'apply'. And so far my analysis has been purely formal. I don't see what exactly happens in the second line.
ADDENDUM:
In other words I am asking not what happens in a std case like: f.andThen(f).apply("Hello")
but in this:
f.andThen(f.andThen(f)).apply("Hello")
There is only 1 apply ‘call’, and 2 ‘andThen’. How are the 2 ‘andThen’’s lambda expressions put together in relation to the ‘apply’ call?
So... not entirely sure if this has been answered before, though I suspect it has and I simply didn't understand it with my current knowledge of the language. As such, a tad bit further of an explanation may be nice, the thread I believe that this may be a duplicate of is
Java Pass Method as Parameter
The basic idea of what I would like to do is something like this:
public void doStuff(String parameter, int parameter, Action/Method/Scope/thing action){
for(parameters){
action();
}
}
which would be called like this:
String parameter1;
int parameter2;
doStuff(parameter1, parameter2){
action
}
this is really generic. Sorry about not having anything specific now. The main thing I'm thinking of is that I've been trying to make an "artillery game" similar to Arcanists (target), or maybe gravitee wars (as a more recent/popular example) the annoying bit is I am frequently working with editing images at a pixel level because the generic bufferedImage/graphic/whatever the normal one & GreenfootImage (greenfoot is the environment I'm using) lack what I want.
really tired right now, please be patient with me. if some of this looks odd of incoherent feel free to ask for clarification, I'm not always the easiest to understand when I'm typing tiredly.
To "pass a method" in Java 8, you need a matching functional interface, i.e. an interface with only one method, whose parameters and return type matches the method you want to pass.
You can use one of the standard methods in the java.util.function package, or you can write your own. E.g. the standard interfaces has various methods with 0, 1, or 2 parameters.
Since your parameters are different type, you can use BiFunction, or you could create your own like this:
public interface StringIntConsumer {
void accept(String s, int i);
}
You can now write code to accept such a method:
public void doStuff(String text, int count, StringIntConsumer action) {
for (int i = 0; i < count; i++) {
action.accept(text, i);
}
}
Then call it using a Lambda Expression:
doStuff("Foo", 10, (name, idx) -> {
// use name and idx here
// will be called 10 times with idx value 0-9
});
As you can see, the parameter names don't need to match.
You have described a BiFunction<T, U, R>,
static <T, U, R> R doStuff(T t, U u, BiFunction<T, U, R> func) {
return func.apply(t, u);
}
And you might call it like
public static void main(String[] args) {
System.out.println(doStuff("Hello", 1, (x, y) -> x + " " + y));
}
which just prints "Hello 1" - but it wasn't clear what action you wanted to do.
In my JavaFX, I attempted to have an ObservableMap<String, String> and a MapChangeListener that listens to keys and values changes(adding/removing a key or the corresponding value) and then does its job.
To make the listener be effective, the method to implement is:
void onChanged(MapChangeListener.Change<? extends K,? extends V> change)
What I first did, with a lambda expression, that doesn't generate any error:
map.addListener((MapChangeListener.Change<? extends String, ? extends String> change) -> {
//code here to implement onChange method
}
And here is what I discovered, that still doesn't generate any error:
map.addListener((MapChangeListener<String, String>) change -> {
//code here to implement onChange method
}
Note the position of the round brackets in this two different examples. The second seems to me to be a cast, but I really don't understand why this second option works.
Can anyone explain me this, please?
P.S.: Actually, I came accross this because I was dealing with a
ObservableMap<String, List<String>>,
that is a multimap, and the first "way" of the two above didn't work (with the right adjustments). /EDIT: I tried again with the first "way" and actually it does work, there was an error on the code I didn't notice END EDIT/. Then I tried with the second option, and it did work, and I was dazed. Then I discovered this same "behaviour" with a simple map <String, String> and this question has arisen.
These two are equivalent. The first one, you are defining the parameter of the lambda expression - note that your bracket covers the whole change parameter. This allows the compiler to know which overload to match it against.
The second one is simply a cast. You are telling the compiler what kind of method signature to match this lambda against. (MapChangeListener<String, String>) casts the whole lambda expression into a MapChangeListener, so the compiler knows that it really is addListener(MapChangeListener). Since you have defined the single parameter defined by MapChangeListener, the compiler doesn't complain that it is wrong either.
Edit
Now that I have a bit more time, I would give you some concrete example that will help you understand a little more in depth.
public class Foo {
public final void bar(IntfA a) {}
public final void bar(IntfB b) {}
public final void bar(IntfC c) {}
}
#FunctionalInterface
public interface IntfA {
void doSomething(Double a);
}
#FunctionalInterface
public interface IntfB {
void doSomething(Integer a);
}
#FunctionalInterface
public interface IntfC {
void doSomething(Double a);
}
public class Test {
public static void main(String[] args)
{
Foo foo = new Foo();
foo.bar(a -> {}); // Ambiguous
foo.bar((Integer a) -> {}); // Okay, this is IntfB
foo.bar((Double a) -> {}); // Ambiguous between IntfA and IntfC
foo.bar((IntfC) a -> {}); // No longer ambiguous since you specified that it's IntfC
foo.bar((IntfC) (a, b) -> {}); // Method signature does not match IntfC
}
}
Edit 2
It seems like you need a little more help here.
When you define a method bar(IntfA), you are expecting an object of IntfA, regardless whether IntfA is an interface type or a class type.
Then, lambda expressions are just compile-time convenient syntax. When I write foo.bar((Integer a) -> {}), the compiler will eventually turn it into Java bytecodes (within .class file) that is equivalent to this:
foo.bar(new IntfB() {
public void doSomething(Integer a) {
}
});
That equivalence is what we call Anonymous Class.
The biggest and possibly only difference in using lambda is, it makes your code shorter. Sometimes it makes your code more readable, sometimes it makes your code less readable.
Since lambda reduces the amount of things that you need to type out, it is very easy to have a lambda expression that is ambiguous for the compiler when there are overload methods like in the example. Remember that the compiler needs to figure out which overload first, then it will help you to instantiate the object for you.
When you write foo.bar((Double a) -> {}), the compile notices that you have a lambda expression that takes in one Double parameter and returns nothing. It will then look at the three overloads of bar(). It notices that both bar(IntfA) and bar(IntfC) takes in a functional interface, and both interface's method takes in one Double parameter and returns nothing. At this point, the compiler is not sure whether it should generate bytecodes equivalent to which two set of codes:
Choice 1:
foo.bar(new IntfA() {
public void doSomething(Double a) {
}
});
Choice 2:
foo.bar(new IntfC() {
public void doSomething(Double a) {
}
});
If you write foo.bar((IntfC) a -> {}), you are already hinting to the compiler that you want it to match foo.bar(IntfC) overload. The compiler sees that you have one parameter of unknown type, but since you have already tell it to match to IntfC, it will assume that parameter is Double.
Now to the last part, calling foo.bar(IntfA) doesn't automatically call the doSomething(Double a) method specified by IntfA. In my example the bar() methods did nothing, but normally people would write something useful.
Example again:
public final void bar(IntfB obj) {
if (obj == null)
System.out.println("I was waiting for an IntfB object but I got nothing!");
else
obj.doSomething(100);
}
foo.bar((Integer a) -> {
System.out.println("I got " + a + " marks for my exam!");
});
This causes "I got 100 marks for my exam!" to be printed on the console.
Lambda in reality doesn't require its type to be expressed unless there is an ambiguity.
If you would not type change it would conflict with addListener(InvalidationListener) that has the same argument length. There are 2 ways of solving this, either by explicitly expressing the type (your first snippet) or by directing the compiler to the correct overload (second), which has nothing to do with lambda semantics.
To reiterate the second point, say you have
void print(String s)
and
void print(Integer i)
calling
print(null) would cause an ambiguity. The solution is print((String)null) which is of course not a type cast, as null has no type, but rather a compiler note.
What does ()->{} represent in java?. Any help would be highly appreciated.
It's a lambda expression, basically a concise way of writing a function. ()->{} is a function that takes no arguments and does nothing. A longer way of writing the same thing:
new Runnable() {
#Override
public void run() {
// nothing
}
};
Let's consider old way of writing functions(i.e methods) in java.
//lets assume this is inside calculate class
public int sum(int a, int b){
return a+b;
}
in java 8 we have something called lambda's in which we have concept called passing behaviours(methods) to another behaviour(methods).
in those case we use syntax like (a,b) -> return a+b;
BiFunction<Integer,Integer,Integer> sum= (a,b)->{
return a+b;
};
System.out.println(sum.apply(1, 2));
Even we can store Function in a variable and pass to another function. you
can see here
now lets see about syntax (a,b) ->{ return a + b};
(a,b) are arguments to function;
and the line of code inside {} represent the behaviour. -> is to separate
both left and right expressions.
you can explore more about java8 and lambda over here
I was reading about currying in functional-programming, and I have a very basic question:
If I have two functions in Java
int add(int x, int y){
return x+y;
}
and I create another method
int increment(int y){
return add(1, y);
}
In the above code, when I wrote increment function, did I actually curry add ?
You have partially applied add. This is related to currying.
In some languages that support partial application, functions are curried by default. you might be able write code like:
increment = add(1)
println(increment(2))
# => 3
A curried function allows you to partially apply that function directly. Java doesn't support that kind of thing without extra machinery.
EDIT:
In Java 8, with lambdas and java.util.function, you can define a curry function.
import java.util.function.Function;
public class Example {
public static <T, U, R> Function<T, Function<U, R>> curry(BiFunction<T, U, R> f) {
return t -> u -> f.apply(t, u);
}
public static int add(int x, int y) {
return x + y;
}
public static void main(String[] args) {
Function<Integer, Function<Integer, Integer>> curriedAdd = curry(Example::add);
// or
// BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
// curriedAdd = curry(add);
Function<Integer, Integer> increment = curriedAdd.apply(1);
System.out.println(increment.apply(4));
}
}
EDIT #2:
I was wrong! I've corrected/modified my answer. As sepp2k pointed out this is only partial function application. The two concepts are related and often confused. In my defense there's a section on the currying Wikipedia page about the mixup.
No, you just call it. You need to pass function as argument, and return partial evaluation of that function to call it currying.