Specify an argument should implement more than one trait - groovy

To illustrate my question, better as an example: Lets say I want to host a triathlon, whereby triathletes have to Swim, Run, Cycle, so I have 3 traits:
trait Swimmer {
abstract void swim()
}
trait Runner {
abstract void run()
}
trait Cyclist {
abstract void cycle()
}
All these traits together make up a Triathlete:
trait Triathlete extends Swimmer, Runner, Cyclist {
}
Which can then do a triathlon:
def triathlon(Triathlete triathlete) {
triathlete.run()
triathlete.cycle()
triathlete.swim()
}
Currently I am defining a DSL in groovy, and in this use case, it doesn't really make sense to define this intermediate trait Triathlete. So is there a way to declare triathlon, using Swimmer & Runner & Cyclist?
I don't know if there is anything in the language itself to do this, I imagine there is a way to do this with AstBuilder or the likes but I am not there yet with my level of groovy to implement something like this, but I am looking for something like this
void triathlon(Swimmer & Runner & Cyclist triathlete) {
triathlete.run()
triathlete.cycle()
triathlete.swim()
}

Ok I figured this out, just putting this for others to use, you can use generics here, pure Java no Groovy needed:
static <T extends Swimmer & Runner & Cyclist> void triathlon(T triathlete) {
triathlete.run()
triathlete.cycle()
triathlete.swim()
}

Related

Is there a clean way to specify Closure parameter type in Groovy?

I'm aware of #ClosureParams annotation. It seems to be covering more complex use cases only though. I'm looking for something like described here at the annotating closures section. Which is similar to the following snippet:
void doSomething(MyType src, #ClosureParams(MyType) Closure cl) { ... }
This example no longer compiles with more recent groovy versions unfortunately (I'm on 2.5.8 at the moment). I know I can achieve equivalent with:
void doSomething(MyType src, #ClosureParams(FirstParam) Closure cl) { ... }
My use case doesn't have any other argument than closure itself though:
void doSomething(#ClosureParams(/* how? */) Closure cl) { ... }
I can hack it like:
void doSomething(#ClosureParams(SecondParam) Closure cl, MyType ignore = null) { ... }
It's far from clean, is it not?
I can as well go:
void doSomething(#ClosureParams(value = SimpleType, options = ['com.somepackage.MyType']) Closure cl) { ... }
It's not only ugly and noisy but as well having type specified as string prevents some IDE features from working. For example MyType refactor-rename or search for usages won't be picked up here.
I guess, there isn't any cleaner way of achieving this so type could be specified as a type not a string and without an extra unnecessary argument, is there?
Something like originally posted by Cédric Champeau in the blog post linked above would be ideal. Which in my case would look like:
void doSomething(#ClosureParams(MyType) Closure cl) { ... }
You may want to consider FromAbstractTypeMethods signature hint instead of SimpleType. It is quite verbose to use, but it gives you benefits that are missing from SimpleType hint class - you can easily refactor types defined in the signatures class, as well as you can find usages of classes used in the signature hint. The main downside is that you need to create additional abstract class per closure signature hints, and the name of the class that contains signatures as abstract methods need to be defined as a constant string (the same problem exists with the SimpleType signature hint.) However, you get a single parameter doSomething method, without adding the second null parameter just to be able to use SecondParam signature hint.
package com.example
import groovy.transform.Immutable
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromAbstractTypeMethods
class MyClass {
static void doSomething(#ClosureParams(value = FromAbstractTypeMethods, options = ["com.example.MySignatures"]) Closure cl) {
cl.call()
}
static void main(String[] args) {
doSomething {
println it.name
}
}
}
#Immutable
class MyType {
String name
int x
int y
}
abstract class MySignatures {
abstract void firstSignature(MyType myType)
abstract void secondSignature(MyType myType, String str)
}
I guess the simple and clean #ClosureParams(String) variant was removed to satisfy other more complex use cases. The API of ClosureParams annotation is fixed and it limits options to array of strings. Maybe it could be achieved by implementing own ClosureSignatureHint - I have tried that several months ago, but I couldn't make IntelliJ IDEA to use my custom class to provide signature hints.

Public groovy method must be public, says the compiler

What is the cause of this error, and how do I fix it?
At first glance, it seems like a defect in the groovy compiler.
:compileIntegrationTestGroovystartup failed:
C:\src\my-project\src\integration-test\groovy\my\project\MyServiceISpec.groovy: 31: The method setup should be public as it implements the corresponding method from interface my.project.MyTrait
. At [31:5] # line 31, column 5.
public void setup() {
^
1 error
My grails integration test looks like this:
#Integration
#Rollback
class MyServiceISpec extends Specification implements MyTrait {
#Autowired
MyService service
OtherService otherService = Mock()
public void setup() {
myTraithMethod()
service.otherService = otherService
}
}
My trait looks like this:
trait MyTrait {
public void setup() {
myTraithMethod()
}
private myTraitMethod() {
...
}
}
Update Added public keyword to the trait setup method.
I think that the source of that problem is AST, because Spock uses AST transformations and compiles the specification. You can read here http://docs.groovy-lang.org/next/html/documentation/core-traits.html#_compatibility_with_ast_transformations this:
Traits are not officially compatible with AST transformations. Some of
them, like #CompileStatic will be applied on the trait itself (not on
implementing classes), while others will apply on both the
implementing class and the trait. There is absolutely no guarantee
that an AST transformation will run on a trait as it does on a regular
class, so use it at your own risk!
You can solve it by renaming setup() method in the trait on traitSetup() for example and calling it from the specification setup() method like this:
#Integration
#Rollback
class MyServiceISpec extends Specification implements MyTrait {
#Autowired
MyService service
OtherService otherService = Mock()
void setup() {
service.otherService = otherService
traitSetup()
}
def 'some test here'() {
...
}
}
trait MyTrait {
void traitSetup() {
myTraitMethod()
}
private myTraitMethod() {
...
}
}
1/ Not sure, but the trait name is ResetsDatabase and your test implements MyTrait.
Possibly some mixup with traits ?
2/ It seems to me that you can't have a public method on the implemented method if your traits says the the method (setup here) is private.

How to make a local extension method avaiable in a function with receiver?

I found an interesting thing, but I couldn't do it. Is there any way to make the local extension method available in a function with receiver.
val list = ArrayList<Any>();
fun <T> Array<T>.bind(context: MutableList<in T>, block: Array<T>.() -> Unit) {
fun Array<T>.save() {
context.addAll(this);
}
block();
}
arrayOf(1, 2, 3).bind(list) {
save(); //todo: how to bind extension in execution scope
};
I know there is an alternative way by introducing another type for the receiver, but I want to avoid it. for example:
interface Savable {
fun save();
}
fun <T> Array<T>.bind(context: MutableList<in T>, block: Savable.() -> Unit) {
val proxy = object : Savable {
override fun save() {
context += this#bind;
}
};
proxy.block();
}
There is no such feature yet, and I think in near future it won't be added either. You should just use your second version. Don't care about adding an wrapper class. The idea of avoiding introducing a wrapper class is actually, as long as you are using JVM backend, just nonsense, because by using local function you are actually adding a local class.
This is the equivalent Java code of your kotlin function, after fixing as you have suggested, with the assumption that your bind function lives in file bind.kt:
public final class BindKt {
public static <T> void bind(T[] receiver, List<? super T> context, Function1<T> block) {
class Local { // the name of local class is unimportant, as it's generated by compiler. It should looks like "package.name.BindKt$bind$X" where X is a number.
public void save(T[] receiver) {
context.addAll(receiver);
}
}
block.invoke(this); // this won't compile. Neither will yours.
}
}
As you can see save is NOT compiled to a static method, which means, if your block somehow ever called that save, an instance of Local must be fist created. So, no matter what you do, as long as you used a local function, there is basically no point in avoiding introduing a wrapper class. Your second solution is good, and just use it. It's both elegant and efficient enough.
If you really don't want add a class/object creation, move these extension functions to a package scope, and let clients import them.

Using abstracts as HashMap keys in Haxe

I'm trying to create a haxe.ds.HashMap where the keys are an object I don't control. Thus, they don't implement the hashCode method and I can't change them to.
I would really like to use an abstract to accomplish this, but I'm getting some compile time errors.
Here is the code I'm playing with:
import haxe.ds.HashMap;
abstract IntArrayKey( Array<Int> ) from Array<Int> {
inline public function new( i: Array<Int> ) {
this = i;
}
public function hashCode(): Int {
// General warning: Don't copy the following line. Seriously don't.
return this.length;
}
}
class Test {
static function main() {
var hash = new HashMap<IntArrayKey, Bool>();
}
}
The compile errors are:
Test.hx:15: characters 19-51 : Constraint check failure for haxe.ds.HashMap.K
Test.hx:15: characters 19-51 : IntArrayKey should be { hashCode : Void -> Int }
But the moment I change my abstract over to a class, it compiles fine:
import haxe.ds.HashMap;
class IntArrayKey {
private var _i: Array<Int>;
inline public function new( i: Array<Int> ) {
this._i = i;
}
public function hashCode(): Int {
// General warning: Don't copy the following line. Seriously don't.
return this._i.length;
}
}
class Test {
static function main() {
var hash = new HashMap<IntArrayKey, Bool>();
}
}
It's the exact same hashCode implementation, just a different context. Is there some way to accomplish this? Or is it a language limitation?
As far as I know, abstracts currently can't satisfy type requirements like this, quoting from the code:
abstract HashMap<K:{ function hashCode():Int; }, V >(HashMapData<K,V>) {
So, I doubt you could do that in a meaningful way.
Important point would be that while abstracts can sometimes provide overhead-free abstractions which is quite useful for optimizations, the time needed to instantiate(probably hidden from sight with abstract Name(Holder) to Holder having #:from Array<Int> and #:to Array<Int>) holder for your array which will have the required method isn't that high(compared to usual runtime overheads), and unless it is a really frequent code, should be your first way to go.
However, the HashMap code itself is quite short and simple: here.
You could just copy it and make it work with your example. Maybe you could even forge a better yet generic version by using interfaces(though I'm not sure if abstracts can actually implement them).

EF generic method overloading

I'd like make possible a generic method overload.
Since I need to create an ObjectSet<..> without knowing the generic type contained in, I wold build something like this:
public IQueryable<T> MyMethod<T>() where T : class, (IMyFirst || IMySecond) //notice the syntax..!
{
if(typeOf(T) is IMyFirst..
else ...
}
How can I reach my purpose..?
Update:
#BrokenGlass wrote:
This type of constraint is not possible in C# - you could however constrain to IFoo and have IMyFirst and IMySecond both implement IFoo.
But that suggestion is not applicable, please see this:
interface1 { property1 {..}}
interface2 { property2 {..}}
interfaceIFoo : interface1, interface2 { }
by any method:
MyWrapper.Retrieve<EntityProduct>(myObjContext); //error-> EntityProduct implements interface1 only!!
by other any method:
MyWrapper.Retrieve<EntityOrder>(myObjContext); //error-> EntityOrder implements interface2 only!!
and here:
public static IQueryable<T> Retrieve<T>(ObjectContext context) where T :class, interfaceIFoo
{
var query = context.CreateObjectSet<T>().AsQueryable();
//...
This type of constraint is not possible in C# - you could however constrain to IFoo and have IMyFirst and IMySecond both implement IFoo.
If you can live with dependencies on Entity Framework you could alternatively also use EntityObject
A disjunctive generic constraint doesn't really make sense. Those constraints provide compile-time information to the method, so there's not much point in constraints that result in an ambiguous type at compile time. For instance, if your method is just going to resort to run-time type checking, you might as well just do this:
public IQueryable<T> MyMethod<T>() where T : class
{
if (typeOf(T) is IMyFirst) ...
else ...
}
If you feel you need the type checking on input and a pseudo-abstraction, perhaps extension methods that happen to be identically named would suffice:
public static IQueryable<IMyFirst> MyMethod(this IMyFirst input)
{
return ...
}
public static IQueryable<IMySecond> MyMethod(this IMySecond input)
{
return ...
}

Resources