I need to pass a java.util.function.Predicate to a Java function. How can I implement it as Lambda in Kotlin?
The Java-Function I need to call:
public void foo(Predicate<String> p)
Java Lambda implemenation ✔ :
foo(text-> true)
Kotlin Lambda implemenation ❌:
foo{text:String -> true}
^^^^^^^^^^^^
Type mismatch.
Required: Predicate<String>
Found: (String) → Boolean
Kotlin-Version 1.2.21
Since Kotlin 1.4
foo({text -> true })
or
foo {text -> true}
Before Kotlin 1.4
These variants work:
foo(Predicate {text -> true })
foo(Predicate {true})
foo({true }as Predicate<String>)
If in case want to declare as a property:
private val normal = Predicate<Int> { true }
private val even = Predicate<Int> { it % 2 == 0 }
private val odd = even.negate()
fun main() {
println("Normal count ${get(normal)}")
println("Even count ${get(even)}")
println("Odd count ${get(odd)}")
}
fun get(predicate: Predicate<Int>): Int {
val filter = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).filter { predicate.test(it)}
println(filter)
val map = filter.map { it * 2 }
println(map)
return map.sum()
}
It works fine, here is a test that compiles with a Java List and the filter method that takes a Predicate as parameter:
val test = Arrays.asList("Hello", "Bye", "World!")
println(test)
println(test.filter { it.startsWith("W") })
Is the last sample code (foo{text:String -> true}) your code that does not compile?
Between the braces, your are supposed to pass the implementation of the lambda, not the type/interface of it. This part is inferred for you!
As of Kotlin 1.4, there is support for Single Abstract Method (SAM) conversion for Java interfaces:
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
From the example in the question, the following works now:
foo { text -> true }
Related
I have following code:
return userService.getAll()
.stream()
.map(User::getRoleName)
.map(roleName -> roleService.findRoleByName(roleName))
.collect(Collectors.toSet());
It seems that roleName -> roleService.findRoleByName(roleName) could be replaced by a method reference (namely a Reference to an instance method of a particular object) however IntelliJ IDEA warns that this may change semantics:
How could it change semantics? Would it change semantics?
If you do not follow the rules of clean functional programming, there may be a change of semantics when you convert a lambda to a method reference.
The difference is that the method reference will be resolved when the stream is being built. But in the lambda expression the code for getting the method can be evaluated in each execution of the lambda.
Here is a short self-contained example for demonstration:
public class Test40 {
public static void main(String[] args) {
Function<Integer, Integer> f2 = n -> 2 * n;
Function<Integer, Integer> f3 = n -> 3 * n;
Function<Integer, Integer>[] funcArray = new Function[1];
funcArray[0] = f2;
Stream.of(1, 2, 3)
.peek(n -> { if (n > 1 ) funcArray[0] = f3; })
.map(funcArray[0]::apply) // Method reference, '::apply' could be omitted
.forEach(System.out::print); // prints 246
System.out.println();
funcArray[0] = f2;
Stream.of(1, 2, 3)
.peek(n -> { if (n > 1 ) funcArray[0] = f3; })
.map(n -> funcArray[0].apply(n)) // Lambda
.forEach(System.out::print); // prints 269
System.out.println();
}
}
How to avoid this problem: Do not use side effects when working with streams. Do not use peek for processing! This method exists mainly to support debugging (have a look at the javadoc).
This is my kotlin class:
class example {
var a = 0
fun add(b: Int, callback: (Int) -> Unit){
a += b
callback(a)
}
}
How do I use this function in a java code?
Edit:
As #Drawn Raccoon mentioned in the comments, you can call the add method from java code simply by returning Unit.INSTANCE:
Java:
example e = new example();
e.add(16, a -> {
// do some work with 'a'
return Unit.INSTANCE;
});
Or call it from kotlin without returning any value:
Kotlin:
add(16) {
a -> // do some work with 'a'
}
Not correct(for correct answer refer to Edit section):
I think you can't use Unit type for output type of callback that will be called from java code. Unit is not recognized in Java.
Instead you can use Void? (I don't know about 'Void' and now I can't test it).
Code in kotlin:
class example {
var a = 0
fun add(b: Int, callback: (Int) -> Void?){
a += b
callback(a)
}
}
And calling it from java:
example e = new example();
e.add(16, a -> {
// do some work with 'a'
return null;
})
And call from kotlin:
val example = example()
e.add(16, { a ->
// do some work with 'a'
null
})
[ In addition, the 'example' is not a good name for kotlin or java classes and try to use upper case, like 'Example' ]
I have only seen examples where the result is a Java list of Scala doubles. I got as far as
def getDistance(): java.util.List[java.lang.Double] = {
val javadistance = distance.toList.asJava
javadistance
}
but this is still a Java list containing Scala doubles (distance is a member of the same class as getDistance).
One has to use the java boxed variant in a map:
def getDistance(): java.util.List[java.lang.Double] = {
distance.toList.map(Double.box).asJava
}
Other than Scala 2.13+ box method, you can use:
def getDistance(): java.util.List[java.lang.Double] = {
val javadistance = distance.toList.map(java.lang.Double.valueOf).asJava
javadistance
}
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
I have a collection and I would like to know if at least one element meets some condition. Essentially, what some does in JavaScript, I would like to do on a collection!
As of Java 8, you can convert the Collection into a Stream and use anyMatch as in the following example.
import java.util.Arrays;
import java.util.List;
public class SomeExample {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, -6, 7);
boolean hasNegative = list.stream().anyMatch(x -> x < 0);
if (hasNegative) {
System.out.println("List contains some negative number");
}
else {
System.out.println("List does not contain any negative number");
}
}
}
Check out Guava's Iterables class and its any() implementation.
More or less the same thing as the Commons Collections example in the other answer, but genericized:
List<String> strings = Arrays.asList("ohai", "wat", "fuuuu", "kthxbai");
boolean well = Iterables.any(strings, new Predicate<String>() {
#Override public boolean apply(#Nullable String s) {
return s.equalsIgnoreCase("fuuuu");
}
});
System.out.printf("Do any match? %s%n", well ? "Yep" : "Nope");
You can use CollectionUtils from Apache commons-collections:
List<Integer> primes = Arrays.asList(3, 5, 7, 11, 13)
CollectionUtils.exists(primes, even); //false
Where even is a predicate:
Predicate even = new Predicate() {
public boolean evaluate(Object object) {
return ((Integer)object) % 2 == 0;
}
}
Or in an inlined version:
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13)
CollectionUtils.exists(primes, new Predicate() {
public boolean evaluate(Object object) {
return ((Integer)object) % 2 == 0;
}
});
Yes, it is ugly for two reasons:
Java does not (yet) support functions as first-class citizens, which are emulated with Single-Abstract-Method interface.
commons-collections does not support generics.
On the other hand in modern JVM languages like Scala you can write:
List(3,5,7,11,13,17).exists(_ % 2 == 0)
Java doesn't have this feature built-in. Javascript's some() accepts a function pointer as an argument, which is not something that's natively supported in Java. But it should be fairly straight forward to emulate the functionality of some() in Java using a loop and and an interface for the callback functionality.