Emitting Java Lambdas in Groovy - java

In developing a Groovy library to be used with Java code, I want to be able to use Java Lambdas than Groovy specific mechanisms.
When accessing this library API from the Java side the user should not need any Groovy specific imports or expose any Groovy specifics features.
Java-specific Lambdas could be pass to the API and also Java-specific Lambdas should be returned from the API.
Is there a way that this can be achieved?
E.g.
def f() {
return { n -> n + 1}
}
The return type of f is groovy.lang.Closure. I want it to be Function.
Also, instead of
def f(Closure c) {
...
c.delegate = this
c.resolveStrategy = DELEGATE_ONLY
...
}
I want to replace Closure c with Function.
In doing so when using it from the Java side Groovy features and API are not exposed to the developer.

The short answer is that you will be able to do this just like in Java.
In java a lamda is accepted as an object that implements a functional interface - a functional interface being an interface that contains only a single abstract method which matches the signature of the lambda you will pass in.
As an example, you can use the Runnable interface which has just a run method with no parameters.
In groovy you will accept an object of type Runnable:
def myGroovyFunction(Runnable r) {
r.run()
}
You can use any functional interface here, for example something from java.util.function or your own interface.
your java code can now pass in a lambda like so:
MyGroovyClass.myGroovyFunction(() -> {
System.out.println("This will be printed by the groovy function");
})

Related

Kotlin - Interfaces as Trailing Lambdas

Which are the rules that make an Interface capable of being used as trailing lambda argument?
I though that the only rule was for it to be having a unique function on its definition, however I got myself into the following problem:
I had this Java interface
public interface ToolbarFragmentCallBack {
void onNavigationClick();
}
Called from a java class:
public void addToolBar(int container, String title, boolean isParent,
ToolbarFragment.ToolbarFragmentCallBack callback) {
//do something
}
Which was called from both Kotlin and Java files:
Kotlin (1):
addToolBar(R.id.toolbar_fragment, toolbarTitle, toolbarParent) {
presenter.onClickNavigationToolBar()
}
Java (2):
addToolBar(R.id.toolbar_fragment, definition.getTitle(), false, () -> {
activity.onBackPressed();
});
However, I recently migrated the interface to Kotlin:
interface ToolbarFragmentCallBack {
fun onNavigationClick()
}
And now the **Kotlin (1) ** implementation calls don't compile, with message
Type mismatch: inferred type is () -> Unit but
ToolbarFragment.ToolbarFragmentCallBack! was expected
Edit:
It is now possible with Kotlin 1.4.
Note, however, that SAM conversions still won't work with standard interfaces, you have to explicitly declare your interface as a functional interface:
fun interface ToolbarFragmentCallBack {
fun onNavigationClick()
}
addToolBar(R.id.toolbar_fragment, toolbarTitle, toolbarParent) {
presenter.onClickNavigationToolBar()
}
Old Answer:
For now Kotlin supports SAM conversions for Java interfaces only
(see docs):
Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.
However, that is about to change with the new version 1.4 (see What to Expect in Kotlin 1.4):
The community has requested us to introduce support for SAM conversions for Kotlin classes. [...] SAM conversions currently only work for Java interfaces and abstract classes. The initial idea behind this design was to use function types explicitly for such use-cases. It turned out, however, that function types and typealiases don’t cover all the use-cases, and people often had to keep an interface in Java only to get a SAM-conversion for it.

Is there a way to print a functional interface?

Suppose I have an interface:
public interface Function {
double function (double input);
}
Now, suppose I have created an instance of this interface somewhere in my main class,
Function f = (x) -> x;
How can I go about printing this function, in plain text?
So, something a bit like this:
int f (double x) {return x}
Running a .toString on this Function prints something like Main$1#6d06d69c. How can I go about getting the java representation of this interface?
Remember that the text of a function (otherwise known as "code") only exists when you write it. You compile this to bytecode which is then run on the Java Virtual Machine. At runtime, the original code which you wrote no longer exists and cannot be easily retrieved.
Unfortunately, the answer (as of Java 9) is that there isn't a simple way to get the toString() method to give you a human-meaningful value for an arbitrary instance of a functional interface.
Here are a couple of alternatives that are applicable for some use-cases:
Instead of using a lambda, implement the interface using a class, and include an appropriate override for the toString() method.
Populate a Map<Function, String> with meaningful names for all of your Function instances.
It would be theoretically possible to build a library that can retrieve the ".class" file for (say) a lambda, analyse it, work out what the bytecodes do, and then produce an appropriate summary. But it would be difficult project.
It would be nice if there was a simple, clean solution to this. Maybe "someone" could suggest it as an RFE for a future version of Java.
You need to call the method in the interface explicitly by supplying a value of double, like below
Function f = (d) -> d;
System.out.print(f.function(2.0));

List out declared methods of a Groovy class from Java

I have a groovy file named sample.groovy, which contains different methods:
class sample {
def doOperation()
{
println("Inside doOperation()")
}
def setData(String str)
{
println("Incoming data : " + str)
}
}
I have defined only 2 methods: doOperation() and setData(), and I want to list out these 2 methods only.
I have used reflection and try to list out methods using getDeclaredMethods(). But it list out above methods and methods like: setProperty, getProperty, setMetaClass, etc.
I want to list out the methods defined in this particular file only.
According to JLS 13.1.7, the "Groovy" methods that are generated should be marked as synthetic:
Any constructs introduced by a Java compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors, the class initialization method, and the values and valueOf methods of the Enum class.
With this in mind, you can filter out the synthetic methods on the class to give you only methods in the source code:
def methods = sample.declaredMethods.findAll { !it.synthetic }
If you're looking for a pure Java solution, you can do the following:
List<Method> methods = new ArrayList<>();
for (Method m : sample.class.getDeclaredMethods()) {
if (!m.isSynthetic()) {
methods.add(m);
}
}
Or using the Java 8 streams API:
List<Method> methods = Arrays.stream(sample.class.getDeclaredMethods())
.filter(m -> !m.isSynthetic())
.collect(Collectors.toList());
What you are asking for doesn't really make (too much) sense.
You see, the Java language knows nothing about the Groovy language.
The point is that Groovy source code will be compiled into JVM bytecode at some point.
This means: all the things that Groovy "adds" compared to the Java language ... are in the end, expressed as JVM bytecode.
In other words: the groovy compiler does its "magic" (for example by adding various methods); and all of that goes into the .class file. And when you then look "into" that .class ... you get all the things in there. As "java reflection" has no notion of "this method was really written by the groovy programmer" versus "this method was added by some groovy transformation process).
Long story short: if at all, you would need to look into mechanisms on the Groovy side of things; because only there you can know that "sample" has those two methods.
You should try below to get only your methods instead of inherited methods :-
def myMethods = MyClass.declaredMethods.findAll { !it.synthetic }
Hope it will help you...:)

What is the most succinct Scala way to invoke a Java 8 functional interface?

Take a Runnable, for example. What is the most succinct way to call this from Scala?
I'm currently doing this:
r { () => runnable-body; null; }
after having declared the following trait:
trait Implicits {
def r(fun: () => Unit) = new Runnable { def run() = fun() }
}
But this has two flaws:
It's only for Runnable, not for all functional interfaces.
There must be a more succinct way to express this. Compare with Java 8's simpler () -> runnable-body.
You could make the adapter take () => Any to avoid the need for the null.
Scala is working on support for Java 8 SAM synthesis but it won't be marked stable until 2.12; you can build with -Xexperimental to enable it in current versions. Other than that as far as I can see you'll need adapters for every case (maybe a macro could help generate them).

How can I implement a generic interface in Rhino JS?

I have an application that contains a generic interface:
public interface IMyInterface<T> {
public int calcStuff(T input);
}
I can clearly implement this in Java:
public class Implementor implements IMyInterface<FooObject>{
public int calcStuff(FooObject input){ ... }
}
I have found a tutorial on implementing Java non-generic interfaces in Rhino and can verify that it works in my context.
As far as I understand Javascript has no generics due to the dynamic type system and other factors, so Rhino does not provide such a concession in its JS parser. Any attempts to do research lead me to a plethora of results about Rhino mocks generic interfaces but not Rhino JS generic interface implementation.
From a Javascript point of few, there are no generics, no interfaces, not even classes. In Javascript you have Objects with functions that may be created from prototypes.
To "implement" a Java interface in Javascript only means, to provide some Javascript object, that has the same function names as the interfaces method names, and these functions have the same number of arguments as the corresponding interface methods.
So to implement the generic example interface you provided, you can write something like this:
myGenericInterfaceImpl = new Object();
// Generic type is supposed to be <String> int calcStuff(String)
myGenericInterfaceImpl.calcStuff = function(input) {
println("--- calcStuff called ---");
println("input" + input);
println("typeof(input):" + typeof(input));
// do something with the String input
println(input.charAt(0));
return input.length();
}
Here it is assumed, that the intended generic class is of type String.
Now lets say, you have a Java class, that accepts this interface with a generic String type:
public static class MyClass {
public static void callMyInterface(IMyInterface<String> myInterface){
System.out.println(myInterface.calcStuff("some Input"));
}
}
You can then call this method from Javascript like so:
// do some Java thing with the generic String type interface
Packages.myPackage.MyClass.callMyInterface(new Packages.myPackage.IMyInterface(myInterfaceImpl)));
Some background information on the topic
If you are interested in what goes on behind the scenes in Rhino, when implementing a Java interface in Javascript, I recommend to have a look at the following Rhino classes:
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/jdk13/VMBridge_jdk13.java
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/InterfaceAdapter.java
Essentially the static method InterfaceAdapter#create() will call VMBridge#newInterfaceProxy(), which returns a Java Proxy for the interface, that uses an instance of InterfaceAdapter to handle method invocations on your interface. This proxy will map any Java method call on the interface to the corresponding Javascript functions.
**
* Make glue object implementing interface cl that will
* call the supplied JS function when called.
* Only interfaces were all methods have the same signature is supported.
*
* #return The glue object or null if <tt>cl</tt> is not interface or
* has methods with different signatures.
*/
static Object create(Context cx, Class<?> cl, ScriptableObject object)
When I first worked with generic interfaces in both Java and Javascript, it also helped me quite a lot to understand what is going on, by step debugging my invocations on the created Rhino proxies (but you will of course need the Rhino source to do that, and setting it up can be a little cumbersome).
Also note, that the default Rhino implementation used by the Java Scripting API does not allow to implement multiple Java interfaces or to extend Java classes. From the Java Scripting Programmer's Guide:
Rhino's JavaAdapter has been overridden. JavaAdapter is the feature by
which Java class can be extended by JavaScript and Java interfaces may
be implemented by JavaScript. We have replaced Rhino's JavaAdapter
with our own implementation of JavaAdapter. In our implementation,
only single Java interface may be implemented by a JavaScript object.
So if you need these features, you will need to install the original Rhino implementation anyway (which makes it easier to set up the source code).

Categories

Resources