Groovy Closure generic return/parameters? - grails

I have a method that should take a Closure with first two parameters Car and Tyre and should return a type of Vehicle.
Is there a way to declare the type of parameters in Groovy Closures?
I am thinking
method(Closure<Vehicle, Car, Tyre> closure);
but what is the correct way?

You can only define the return type of a Closure, ie: Closure<Vehicle>
As of Groovy 2.3, you can use #ClosureParam to tweak the type system (see "Tweaking the type system" here), but Groovy 2.3 is not currently in Grails I believe...

The generic parameter on Closure is used for the return type. Closure<String> shall return a string.
The parameters may be declared using the #ClosureParams annotation
http://beta.groovy-lang.org/docs/groovy-2.3.0-beta-1/html/gapi/groovy/transform/stc/ClosureParams.html

Related

Groovy named parameter causing ClassCastException

I have a Groovy script which is run in Jenkins. For context, I am using the SAML Plugin, and specifically using the SamlSecurityRealm constructor. This works fine.
However, to improve readability, I have attempted to used named parameters. The parameter binding, which is of type String, is causing the following exception:
java.lang.ClassCastException: java.lang.String cannot be cast to groovy.lang.Binding
My usage is like this:
binding = 'String value'
This syntax is working for all of the other parameters, and if I remove just this one named parameter, the script runs.
I am familiar with Java and Scala, but not so much with Groovy. binding does not seem to be a keyword, but I am assuming I need to escape it somehow? Wrapping it in single or double quotes, or backticks is also not working.
if you are inside groovy Script then binding = XYZ tries to call Script.setBinding(XYZ)
https://docs.groovy-lang.org/latest/html/api/groovy/lang/Script.html
unless you declare a variable binding like this:
def binding = XYZ

Why does dart not allow method overloading?

I tried to use method overloading in some dart code and quickly learned that overloading is not offered in dart.
My questions are: why is it not offered, and what is the recommended alternative? Is there a standard naming convention since methods that do the same thing but with different inputs must have different names?
Is it standard to use named parameters and then check that the caller has supplied enough information to complete the calculation?
Say I have a method that returns how much money someone makes in a year, called yearlyIncome.
In Java, I would create a method like this
double yearlyIncome(double hourlyRate, double hoursWorkedPerYear)
And maybe another method like this
double yearlyIncome(double monthlyRate, int monthsWorkedPerYear)
and so on. They're all used to calculate the same thing, but with different inputs. What's the best, standardized way to do this in dart?
Thanks so much in advance.
Function overloading is not supported in Dart at all.
Function overloading requires static types. Dart at its core is a dynamically typed language.
You can either use different names for the methods or optional named or unnamed parameters
// optional unnamed
void foo(int a, [String b]);
foo(5);
foo(5, 'bar');
// optional named
void foo(int a, {String b});
foo(5);
foo(5, b :'bar');
Optional parameters can also have default values. Optional named and unnamed parameters can not be used together (only one or the other for a single function)
In the case of a constructor you can use named constructors as an alternative
Dart did not support overloading originally because it was a much more dynamic language where the declared types did not have any semantic effect. That made it impossible to use static type based overload resolution.
Dart has since changed to be more statically type, and there is nothing fundamentally preventing Dart from adding overloading today, except that it would be a huge work and a huge change to the language. Or so I'd assume, because there isn't any obvious design that isn't either highly complicated or hugely breaking.
What you do instead in Dart is to use optional parameters. A method like:
String toString([int radix]);
effectively have two signatures: String Function() and String Function(int). It can act at both signatures.
There are definite limits to how far you can go with just optional parameters, because they still need to have exactly one type each, but that is the alternative that Dart currently provides. (Or use different names, but that's not overloading, you can do that in languages with overloading too).
Optional parameters is also one of the complications if we wanted to add overloading to the Dart language - would existing functions with optional parameters would count as multiple overloadings? If you declare a class like:
abstract class WithOverloading {
String toString();
String toString(int radix);
}
is that then the same signature as:
abstract class WithoutOverloading {
String toString([int radix]);
}
Probably not because you can tear off the latter and get one function with an optional parameter, and you might not be able to tear off both functions from the former and combine them into one function. Or maybe you can, that's why it's not a trivial design question how to include overloading into the existing Dart language.

Dart generics not reified as per the docs

I'm trying to pass a type in order to make use of the type information, but that types doesn't appear to be pass through.
I went back to the docs to double check that Dart generics are in fact reified and according to the docs, they are:
I call hydrate on a response which morphs the content of response object:
response.hydrate<BoqVO>();
I'm expecting T to be of type BoqVO:
class Response {
...
void hydrate<T>() {
print(T.runtimeType); // always prints _Type
if (T is BoqVO) {
print("IF");
} else {
print("ELSE"); // always goes into ELSE block
}
}
...
}
... but it's not.
Replacing response.hydrate<BoqVO>(); with response.hydrate(new BoqVO()); and changing the method signature to
void hydrate(T t) {
works if i now use lowercase t, but one shouldn't have to instantiate the object in order for reified generics to be available.
Any ideas why Dart is doing this or what i'm missing for reified generics to work correctly?
PS: I'm not on Dart 2 yet, currently on Dart 1.24.3
As Günther Zöchbauer has said, the type parameter doesn't work in Dart 1.24.
The following explains what would happen if you tried the same code in Dart 2.0, where it would also not work, because it uses the type parameter incorrectly.
The code T.runtimeType treats T as an expression. When a type, including a type parameter, is used as an expression, it evaluates to an instance of the class Type. What you print is the runtime type of that Type object (where _Type is an internal platform implementation of Type).
To print the real type, just print(T) (that still converts T to a Type object, but one representing the type BoqVO and with a toString that includes the BoqVO name).
Likewise for T is BoqVO, you evaluate T to a Type object, and since Type doesn't implement BoqVO, that test is always false. There is no simple way to test if the type of a type parameter implements a specific other type, but you can hack around it as <T>[] is List<BoqVO>.
Generic collections were supported from the beginning and they got some type support, but generic methods were only experimental in Dart 1 and reified type parameters were only added in Dart 2 pre releases.

What does a colon after a tuple but before another type mean within a method signature?

What does a colon that's positioned after a tuple but before another type mean within a method signature?
Here's the syntax:
member this.Post (portalId : string, req : PushRequestDtr) : IHttpActionResult =
Here's the context:
type PushController (imp) =
    inherit ApiController ()
    member this.Post (portalId : string, req : PushRequestDtr) : IHttpActionResult =
        match imp req with
        | Success () -> this.Ok () :> _
        | Failure (ValidationFailure msg) -> this.BadRequest msg :> _
        | Failure (IntegrationFailure msg) ->
            this.InternalServerError (InvalidOperationException msg) :> _
Specifically, what does this method signature mean?
Does this method take two parameters or one parameter?
I understand this:
(portalId : string, req : PushRequestDtr)
But I'm confused about this syntax that's appended to the end of it:
: IHttpActionResult
That would be the return type, i.e. the type of the value returned by the method.
From the F# online docummentation:
https://learn.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/methods
// Instance method definition.
[ attributes ]
member [inline] self-identifier.method-nameparameter-list [ : return-type ]=
method-body
In this case return_type is IHttpActionResult, which means this method will return an object that implements the IHttpActionResult interface.
Also, although (portalId : string, req : PushRequestDtr) looks like a tuple (and in a certain way it is syntax-wise) it is not, in fact, treated as a tuple. In this case, this is a specific F# syntax for declaring method arguments while defining a method of a F# object. This is the part represented by method-nameparameter-list in the F# method template declaration. This means that the Post method receives two arguments: portalId and req, not a single argument as a tuple.
Specifically, this syntax of a list of arguments that looks like a tuple but that they are not a tuple has to be used when declaring method arguments instead of function arguments. The member keyword is the one that makes this line a method declaration instead of a function declaration.
--
Regarding the :> operator: This is a cast operator. More specifically a upcasting operator (which changes the type of a more derived type to the type of some higher type in the type hierarchy).
In this case, it is being used to explicitly tell the compiler that each branch in the match expression will return some type that is derived (or that implements) IHttpActionResult. I am not quite sure why this cast is needed (something to do with F# not being able to infer the correct type in this context, see this other question: Type mismatch error. F# type inference fail?) but in fact, it is casting every possible return value to IHttpActionResult which is the method's return type.
https://learn.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/casting-and-conversions

binding request parameters to action arguments

In Grails you can declare a controller action like this:
def create(Integer foo, Integer bar) {
}
And if your HTTP request has parameters named foo and bar with values that can be converted to an Integer, the parameters will be assigned these values. I'm wondering how Grails can do this, because my understanding is that at the JVM bytecode level, a method's formal parameter names are not available. Is this witchcraft or am I misunderstanding something?
Basically what happens is that there's an AST transform that adds a new method with no args and the same name. This new method has logic in it to do the data binding based on the declared types of your "real" method, and then call your method. That's why the types are required (otherwise there's no way to do a conversion) and why you cannot have method overloads.
The inability to have overloaded methods is easy to work around though. Say you wanted an action
def foo(String bar)
and another
def foo(String bar, Integer wahoo)
In this scenario just keep the 2nd method and check to see if wahoo is null.
It's also important to use object parameter types and not primitives. If you use int/long/boolean/etc. and there is no provided parameter, you would get a NPE (since zero is not an acceptable conversion from null for numbers, and either is false for booleans).
You can get a decent sense for what's going on if you decompile the class using JD-GUI or another decompiler.
The fact that Grails controllers are Groovy classes helps quite a lot. Looking through the source code for controllers you can see where it makes heavy use of AST transformations, in particular the MethodNode. So, before it becomes bytecode the "witchcraft" is done. :)

Resources