How to read with java a callback from a kotlin class (Android) - java

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' ]

Related

How to implement a java.util.function.Predicate as Kotlin lambda?

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 }

Scala symbol to java enum

I am using a spray-routing which is pretty elegant with using symbols for parameters. However I am dealing with some legacy code and need to use java enum. Is there some elegant way how to convert scala symbol to java enum?
So the desired code would look as follows:
post {
parameters(('adId.as[String], 'propertyType.as[TypNe])).as(Import) { imp:Import =>
complete {
adImporterService ! imp
StatusCodes.Accepted
}
}
where TypNem is java enum and Import is a scala case class. Instead of
post {
parameters(('adId.as[String], 'propertyType.as[String])) { (aId,pType) =>
complete {
adImporterService ! Import(aId,TypNe.valueOf(pType.toUpperCase()))
StatusCodes.Accepted
}
}
}
For Java Enum PropertyType
public enum PropertyType {
AAA, BBB, CCC
}
You need to provide custom Deserializer
implicit val propertyTypeDeserializer =
new Deserializer[String, PropertyType] {
def apply(s: String): Deserialized[PropertyType] = {
Try(PropertyType.valueOf(s)) match {
case Success(pt) =>
Right(pt)
case Failure(err) =>
Left(MalformedContent("Wrong property type. Accepted values: ${PropertyType.values}", Some(err)))
}
}
}
def receive: Receive = runRoute {
path("test") {
parameter('prop.as[PropertyType]) { case prop =>
get {
complete(s"Result: $prop. Class: ${prop.getClass}")
}
}
}
}
Solution from #Dici also works and much smaller, but with custom Deserializer you are more flexible with error handling
You can use an implicit declaration to improve the readability :
implicit def strToTypeNe = TypNe.valueOf(pType.toUpperCase())

How to check if a scala class is assignable from a java class

I want to be able to check if a certain Scala class is assignable from a certain Java class. As stated here it is not always possible to do D.class.isAssignableFrom(A.class).
Basically what I need is something like this:
def isAssignableFrom(scalaClass: Class[_], javaClass: Class[T]): boolean = {
// magic
}
I have tested:
def m[T: ru.TypeTag, S: ru.TypeTag](x: T, y: S): Boolean = {
val leftTag = ru.typeTag[T]
val rightTag = ru.typeTag[S]
leftTag.tpe <:< rightTag.tpe
}
as stated in the link from above. But it complains about the Java class not having a TypeTag:
error: No TypeTag available for Class[T]
I'm not that familiar with Scala yet so maybe there is a really simple way of doing this?
I managed to solve it like this:
def isAssignableFrom(scalaClass: Class[_], javaClass: Class[T]): Boolean = {
val javaClassType: ru.Type = getType(javaClass)
val scalaClassType: ru.Type = getType(scalaClass)
scalaClassType.<:<(javaClassType)
}
def getType[T](clazz: Class[T]): ru.Type = {
val runtimeMirror = ru.runtimeMirror(clazz.getClassLoader)
runtimeMirror.classSymbol(clazz).toType
}

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

clojure/scala interop?

I am attempting to interop to this simple scala code, but am having some troubles.
package indicators
class DoubleRingBuffer(val capacity:Int=1000) {
var elements = new Array[Double](capacity);
private var head=capacity-1
private var max=0
def size ():Int = {
return max+1
}
def add(obj:Double):Double = {
head-=1
if (head<0) head=capacity-1
return set(max+1,obj)
}
def set(i:Int,obj:Double):Double = {
System.out.println("HI")
if (i>=capacity || i<0)
throw new IndexOutOfBoundsException(i+" out of bounds")
if (i>=max) max=i
var index = (head+i)%capacity
var prev = elements(index)
elements(index)=obj
return prev
}
def get(i:Int=0):Double = {
System.out.println("size is "+size())
if (i>=size() || i<0)
throw new IndexOutOfBoundsException(i+" out of bounds")
var index = (head+i)%capacity
return elements(index)
}
}
In clojure, i do this
(import 'indicators.DoubleRingBuffer)
(def b (DoubleRingBuffer. 100))
(pr (.size b)) ;;ERROR: No matching field found: size for class indicators.DoubleRingBuffer
(pr (.get b 33)) ;;returns 0: should throw an index out of bounds error!
(pr (.get b 100)) ;;throws index out of bounds error, as it should
In addition, i do not get any output to the console! Testing this code using scala works as expected. Whats going on here and how can i fix it so that clojure can use the scala code?
Try these in REPL:
(class b) will probably tell you it's indicators.DoubleRingBuffer.
(vec (.getDeclaredMethods (class b))) will give you a vector of all methods declared in your class as if it was a Java class, so you can see their signatures.
Now, call your methods as seen in the signatures, with these method names and parameters.
I have a feeling the problem is in Scala's dealing with default value for method parameter.
EDIT: As OP described in a comment, it isn't.
If that doesn't work you can try to decompile your Scala bytecode to Java to find out how does DoubleRingBuffer class look like.

Categories