ros2dart / dartros1

A ROS1 client library for dart
Apache License 2.0
20 stars 11 forks source link

Make Typing Less Verbose #13

Closed TimWhiting closed 3 years ago

TimWhiting commented 4 years ago

For whatever reason I had to make the services take three type parameters to make them work, action servers require even more. I'm not sure we can realistically get rid of the type parameters, but it would be great if we could figure out how to get the type inference to work for us better. Just passing in an instance of the class to the methods isn't able to infer the parameters. Probably an issue of covariance or something. I wonder if we make the message constructors const, and have a const static instance for the $prototype, if the covariance issue would go away, and type inference would be able to infer the types. If not, we should at least have some documentation that type parameters are needed, or try to reduce the verbosity in some other way. I really don't want to resort to dynamic, because that makes both dartros and the user's code more prone to errors.

knuesel commented 3 years ago

From quick and incomplete tests it looks like we could replace

  SimpleActionServer<
      CoffeeGoal,
      CoffeeActionGoal,
      CoffeeFeedback,
      CoffeeActionFeedback,
      CoffeeResult,
      CoffeeActionResult,
      CoffeeAction> server;

with

  SimpleActionServer<CoffeeAction> server;

because CoffeAction is already parametrized with the other types. I'll try to test it more seriously when I have time...

TimWhiting commented 3 years ago

The problem with having fewer type parameters is that if you pass in just CoffeeAction, you cannot strictly type the methods for returning result as being type CoffeeActionResult / CoffeeResult, even though CoffeeAction has that in its type parameter: i.e. you cannot extract type parameters. If you know a way to work around that, feel free to try!

knuesel commented 3 years ago

I gave up, stuck as you said trying to extract the type parameters.

TimWhiting commented 3 years ago

I have an idea that might work. I can give it another try in a week or so.

TimWhiting commented 3 years ago

Okay, I was able to do it. This commit resolves this issue I believe.

@knuesel Published dartros 0.0.5 with the fix, but you'll probably have to make fixes to wherever you use Actions / Services in your code. Nothing changed with the message generation.

knuesel commented 3 years ago

Excellent! The trick was to avoid nested generic types?

TimWhiting commented 3 years ago

This is the trick:

/// The old one only said that whatever we passed in *extends* RosServiceMessage<C,R>
ServiceServer<C, R, T> advertiseService<C extends RosMessage<C>, R extends RosMessage<R>,
 T extends RosServiceMessage<C, R>( String service, T messageClass, R Function(C) callback) {}

/// Now it says that whatever we pass in *is* a RosServiceMessage parameterized by those types, 
/// therefore it can extract the types
ServiceServer<C, R> advertiseService<C extends RosMessage<C>, R extends RosMessage<R>>
   (String service, RosServiceMessage<C, R> messageClass, R Function(C) callback) {}

So I just had to get rid of the last level of 'extends' in the generic typing.