According to documentation, executeBlocking method of Vertx interface has following signature:
<T> void executeBlocking(Handler<Future<T>> blockingCodeHandler, boolean ordered, Handler<AsyncResult<T>> resultHandler)
The question is, why (from formal perspective) following makes Java unable to infer generic type for Future<T> (it's inferred to Future<Object>):
vertx.executeBlocking((deploymentFuture) -> {
this.deploy();
deploymentFuture.complete(new Boolean(true));
}, (asyncResult) -> {
start.complete();
});
Even though deploymentFuture is clearly assigned with Boolean. Only this explicit call gives Java idea of Future<Boolean>:
vertx.<Boolean>executeBlocking((deploymentFuture) -> {
this.deploy();
deploymentFuture.complete(new Boolean(true));
}, (asyncResult) -> {
start.complete();
});
Why it's so problematic to infer types in such use case? Is is because type invariance (similar case to ArrayList<Integer> vs ArrayList<Number>).
Basically without explicit call type I'm thrown away with
No instances of type variable T exist so that Future<T> conforms to Future<Object>
Related
I am currently working on a go project where I define an interface to use in another file. My workflow works but I'm confused at either why there doesn't seem to be any "auto-complete" for protocols or why I cannot find it, I am using VSCode.
First of all, I am not fluent in go at all so if I misuse the term "object" for example that's because I don't know any better.
Let's say the interface looks like that:
type TestInterface interface {
Function1()
}
and my function to pass an object of that interface to looks like that
func Start(obj TestInterface) {
...
Now, in order to define a type that I can construct an object of, I do
type TestInterfaceType int
and because I have to conform to the interface defined, I need to apply these functions to my "new" type
func (e TestInterfaceType) Function1() {
fmt.Println("Test")
}
I am then able to construct an object
var testInterfaceTypeObject TestInterface
testInterfaceTypeObject = TestInterfaceType(1)
and passing that object to my Start() function above which expects a type of that interface works fine since the object of my "new type" has the functions defined that are defined on the interface.
Everything until here works as I have expected, or at least it works for me.
Now if I add another function to the TestInterface but I do not apply that new function to my TestInterfaceType, I see an error coming up that is InvalidIfaceAssign:
InvalidIfaceAssign occurs when a value of type T is used as an
interface, but T does not implement a method of the expected
interface.
I understand why this is happening, I also have to do the func (e TestInterfaceType) ... for my new function but here is my question:
Is there a way to automatically generate empty mock functions for the missing functions? In Java for example, the IDE offers me to add the missing functions (without functionality of course, but at least they are there, ready for me to write logic into them)?
In other words, once I add Function2() to TestInterface, can I make it automatically do
func (e TestInterfaceType) Function2() {
}
wherever I use that interface?
I am trying to execute a transaction on a Redis instance from within Spring Boot application written in Kotlin. I have followed the recommendation in Spring Doc on the best practice to achieve this.
I am struggling with the Kotlin implementation, however. Specifically, I don't know how to implement the Java generic interface with a generic method to make it work in the Kotlin code:
redisTemplate.execute(object : SessionCallback<List<String>> {
override fun <K : Any?, V : Any?> execute(operations: RedisOperations<K, V>): List<String>? {
operations.multi()
operations.opsForValue().set("key", "value")
return operations.exec()
}
})
The code above complains that the set method expects parameters with types K and V respectively but String is found instead.
Is there an elegant way how to inline the interface implementation in Kotlin without having to use unchecked casting or other convoluted approaches to make this work?
I think you're facing this problem due to poor interface definition for SessionCallback and the framework itself is doing unsafe casts themselves.
You see, if we take a look into the SessionCallback definition over here we can see that it looks as follows:
public interface SessionCallback<T> {
#Nullable
<K,V> T execute(RedisOperations<K,V> operations) throws DataAccessException
}
The generics K,V referring to the type of keys and values from your Redis are not parameters of the SessionCallback interface and that's why the kotlin compiler is having a hard time inferring the type of these: Because the execute function only takes a parameter of type SessionCallback<T> without passing the types of keys and values as parameters to that interface.
Your best-effort might be to provide a nice wrapper around that API using extension functions and inline generic types by doing some controlled unsafe casts.
Something like this might be enough:
inline fun <reified K : Any?, reified V: Any?, reified T> RedisTemplate<K, V>.execute(crossinline callback: (RedisOperations<K,V>) -> T?): T?{
val callback = object : SessionCallback<T> {
override fun <KK, VV> execute(operations: RedisOperations<KK,VV>) = callback(operations as RedisOperations<K, V>) as T?
}
return execute(callback)
}
Which then you can consume by doing:
fun doSomething(redisTemplate: RedisTemplate<String, String>) {
redisTemplate.execute { operations ->
operations.multi()
operations.opsForValue().set("key", "value")
operations.exec() as List<String>
}
}
And yes, you need to cast the .exec() result because nobody bothered using generics and returns a List<Object> as you can see on the official documentation
I am trying to learn to how generics act in Compile and RunTime stages comparing with Protocols.
I know how to protocols react with existential types. Protocols are existential types so in compile stages step by step they taking the the Car type
struct Car: Drivable {
let numberOfWheels = 4
func drive() { }
}
car =
payload_data_0 = 0x0000000000000004,
payload_data_1 = 0x0000000000000000,
payload_data_2 = 0x0000000000000000,
instance_type = 0x000000010b50e410
ExistentialContainers`type metadata for
ExistentialContainers.Car,
protocol_witness_0 = 0x000000010b50e1c8
ExistentialContainers`protocol witness table for
ExistentialContainers.Car: ExistentialContainers.Drivable
in ExistentialContainers)
What about generics ? I really wonder how act in compile and runtime stages. They use pointers right ? when at Compile time ? In runtime everything is ready for Generics.
Also this example seems same but one is compile other is not..
protocol Returnable {
associateType ReturnType
}
//This will compile
func returnTheType<T: Returnable>(object: T) -> T.ReturnType { } ✅
//This won't compile
func returnTheType(object: Returnable) -> object.ReturnType { } ❌
func startTravelingWithCar(transportation: Car) { }
I suppose you have a function like this so,
Behind the scenes the function also receives the car’s PWT and VWT, giving the function the necessary information to be able to set up a value buffer if necessary and determine the car object’s protocol specific function implementation of drive(). This newly generated function is now type specific, giving you access to any associated types of the Car object and all of this type information is determined at compile time — which is part of the reason why we can have an associated type be the return type of a generic function, but can’t do the same for protocol based functions.
So, while this is quite a kotlin-dsl for gradle specific issue, I think it overall applies to the kotlin language itself, so I am not going to use that tag.
In the gradle API, the class Action<T> is defined as:
#HasImplicitReceiver
public interface Action<T> {
/**
* Performs this action against the given object.
*
* #param t The object to perform the action on.
*/
void execute(T t);
}
So ideally, this should work in kotlin (because it is a class with a SAM):
val x : Action<String> = {
println(">> ${it.trim(0)}")
Unit
}
But I get the following two errors:
Unresolved reference it
Expected Action<String> but found () -> Unit
Fwiw, even Action<String> = { input: String -> ... } doesn't work.
Now here's the really intriguing part. If I do the following in IntelliJ (which btw, works):
object : Action<String> {
override fun execute(t: String?) {
...
}
}
IntelliJ pops the suggestion Convert to lambda, which when I do, I get:
val x = Action<String> {
}
which is better, but it is still unresolved. Specifying it now:
val x = Action<String> { input -> ... }
gives the following errors Could not infer type for input and Expected no parameters. Can someone help me with what is going on?
This is because the Action class in gradle is annotated with HasImplicitReceiver. From the documentation:
Marks a SAM interface as a target for lambda expressions / closures where the single parameter is passed as the implicit receiver of the invocation (this in Kotlin, delegate in Groovy) as if the lambda expression was an extension method of the parameter type.
(emphasis mine)
So, the following compiles just fine:
val x = Action<String> {
println(">> ${this.trim()}")
}
You could even just write ${trim()} and omit the this in front of it.
You need reference the function with class name, like:
val x: Action<String> = Action { println(it) }
I'm wondering if this is something that's done in Go or if I'm thinking about it all wrong: composing type x interface and type x struct so my interface methods have access to specific data too:
The C programmer in my wants to do this:
type PluginHandler interface {
onLoad()
pm *PluginManager
}
func (ph PluginHandler) onLoad() {
pm.DoSomething()
}
There I have an interface defined with a function, but also some data I want to pass to those functions but this is a syntax error.
So is this something that's doable in Go through some other method or am I just thinking about the problem wrong?
You have defined onLoad incorrectly. You cannot define a function directly on interface type.
Once you have an interface, you need another type to implement methods specified in the interface. For example, if another type implements onLoad method, they automatically (implicitly) implement the interface PluginHandler.
The other thing you need to do is change the interface function type to accept the required data:
type PluginHandler interface {
onLoad(*PluginManager)
}
struct SomeType {
// ...
}
func (s SomeType) onLoad(pm *PluginManager) { // SomeType now implements
pm.DoSomething() // PluginHandler interface.
}
This way, you get to inject whichever PluginManager required by PluginHandler.
Also, you can use SomeType as a PluginHandler type whereever required.
func someFuntion(ph PluginHandler) {
// ...
ph.onLoad(pm)
// ...
}
Can be called with an input argument of type SomeType:
s := SomeType{}
someFunction(s)
TL;DR; There is no direct translation to Go.
Long answer:
Go interfaces are only methods.
Go structs are only data (with the possibility of receiver methods).
You can reference, and even embed interfaces within structs:
type Frobnicator interface {
Frobnicate() error
}
type Widget struct {
Frobnicator
WidgetName string
}
But that's not really what you're talking about.
The best answer to your dilema is, I believe: Take a step back. You're focusing on the trees, and you need to look at the forest. Go takes a different approach than C, or classical OO languages like C++ and Java.
Look at the general problem to be solved, and find solutions to that in Go. This can be a painful process (I can say from experience), but it's really the only way to learn the new way of thinking.
Just for the record, you can add extra methods to an existing type, by introducing another (indirection) type as:
type HandlerManager PluginManager
func (x *HandlerManager) onLoad() {
((*PluginManager)(x)).DoSomething()
}
And if you need to go with a more generic solution, a combination of Adapter & Strategy patterns could do:
type PluginHandlerAdapter struct{ _onLoad func() }
func (x *PluginHandlerAdapter) onLoad() {
x._onLoad()
}
Used like (public/private access ignored):
type PluginManager struct {
PluginHandlerAdapter
}
func NewPluginManager() *PluginManager {
res := new(PluginManager)
res._onLoad = res.DoSomething
return res
}