Explain #:remove #:generic metadata combination - haxe

Consider class with type parameter, that should be used as Map key.
class Foo<K> {
var map: Map<K, Dynamic> = new Map();
}
This does not compile with error Type parameters of multi type abstracts must be known.
The reason is understandable - Map is abstract and it's underlying type is selected based on key type, so key type should be known when compiling new Map() expression. On the other hand non-generic type with type parameters are compiled once for all parameters.
Looks like adding #:generic metadata should help. But actually it does not. My guess was that this is because haxe compiler compiles #:generic types the same as it does with non-generic types, and only then does some extra work for generic type. So I was thinking that having a Map with key type defined by type parameter is impossible in haxe.
But recently I've stumbled upon this issue: https://github.com/HaxeFoundation/haxe/issues/2537
Simn's answer there says, that this can be done by adding #:remove #:generic metadata. And it actually works.
#:remove #:generic
class Foo<K> {
var map: Map<K, Dynamic> = new Map();
}
For me this looks like magic and I'm not comfortable with this. In documentation I only see that
#:remove Causes an interface to be removed from all implementing classes before generation. That does not explain why this works.

If you replace Map by haxe.ds.BalancedTree and use only #:generic without #:remove, you will see your class Foo generated on your target containing new BalancedTree< object, object > (object is Dynamic). That means, Foo class holds general BalancedTree< object, object > type, while Foo_String for example holds generic BalancedTree< string, object > type. Now, if you go back to your Map, you will see that "Abstract haxe.ds.Map has no #:to function that accepts haxe.IMap< Foo.K, Dynamic >", e.g. no Map< Dynamic, Dynamic > implementation exists. That's why you need to use #:remove which will actually stop generation of Foo class, or at least, remove new Map< Dynamic, Dynamic > from the Foo (#:remove "Causes an interface to be removed" is misleading here)

Related

In Groovy, casting between collection implementations copies source instead

The following code
void testReference() {
List<String> source = new ArrayList<>()
source.add("element")
List reference = (ArrayList)source // all ok, creates reference as types match
assertSame(source,reference)
List copyNotReference = (LinkedList)source // should fail on GroovyCastException, creates copy instead
assertNotSame(source,copyNotReference) // this works, copy is a different object
copyNotReference.add("second element")
println source
println copyNotReference
}
only works in Groovy. In Java it fails on attempt to cast ArrayList to LinkedList.
In Groovy it creates a LinkedList instance, calling constructor
public LinkedList(Collection<? extends E> c)
and copying source data to the new instance.
The test outputs
[element]
[element, second element]
That behaviour only occurs when casting types that are subtypes of collections.
Question
What Groovy mechanism is responsible for this unexpected behaviour?
Groovy allows coercion of objects via casting them (asType). This is implemented for collections.
See the source
Converts the given collection to another type. A default concrete
type is used for List, Set, or SortedSet. If the given type has
a constructor taking a collection, that is used. Otherwise, the
call is deferred to {#link #asType(Object,Class)}. If this
collection is already of the given type, the same instance is
returned.

Nomin automap causes infinite loop

I am using Nomin for mapping tasks. As taken from the documentation of Nomin it should be able to map fields with the same name by itself in case automapping has been activated. When activating it, it causes an infinite loop exception.
I have the following:
mappingFor a: CoinsOnMarketPlace, b: Coin
// automap() // when deactivated it works fine, when activated infinite loop
a.coin.name = b.name
a.coin.rank = b.rank
a.priceUSD = b.priceUSD // Could be automapped
a.priceBTC = b.priceBTC // Could be automapped
...
Exception:
org.nomin.core.NominException: ./net/hemisoft/ccm/repository/coinmarketcap2coin.groovy: Recursive mapping rule a = b causes infinite loop!
One thing worth adding regarding your use case - this Recursive mapping rule a = b causes infinite loop! exception is thrown because you use groovy classes in your mapping rule. Nomin uses ReflectionIntrospector and what's important:
It performs getting/setting properties using accessor methods which are called through the Java reflection mechanism. ReflectionIntrospector uses supplied NamingPolicy instance to determine accessor methods. JbNamingPolicy is used by default, this implementation cerresponds the JavaBeans convention. Its InstanceCreator named ReflectionInstanceCreator instantiates objects using Class.newInstance().
Source: http://nomin.sourceforge.net/introspectors.html
A simple Groovy class like:
class Entity {
String name
String somethingElse
}
gets compiled to a Java class that implements GroovyObject providing following methods:
public interface GroovyObject {
Object invokeMethod(String var1, Object var2);
Object getProperty(String var1);
void setProperty(String var1, Object var2);
MetaClass getMetaClass();
void setMetaClass(MetaClass var1);
}
In this case ReflectionInstanceCreator combined with automap() resolves following mappings:
a.property = b.property
and
a = b
where a = b mapping comes from MetaClass getMetaClass() getter method I suppose, because there is no mapping like a.metaClass = b.metaClass resolved. a.property = b.property gets resolved because of Object getProperty(String var1) method.
Solution
This problem can be solved by specifying explicitly ExplodingIntrospector for your mapping script that:
It performs getting/setting properties using a class field immediately through through the Java reflection mechanism and may be useful in case when domain object don't provide accessors for their properties. Supplied instance creator is ReflectionInstanceCreator.
Source: http://nomin.sourceforge.net/introspectors.html
All you have to do is to add
introspector exploding
right below mappingFor a: ..., b: ... header. For example:
import mypackage.Entity
import mypackage.EntityDto
mappingFor a: Entity, b: EntityDto
introspector exploding
automap()
a.test2 = b.test1
Tested with two Groovy classes, worked like a charm. Hope it helps.

F# attributes, typeof, and "This is not a constant expression"

EDIT: Added a more complete example, which clarified the problem.
Some .NET attributes require a parameter of type Type. How does one declare these parameters in F#?
For example, in C# we can do this:
[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Truck))]
class Vehicle { }
class Car : Vehicle { }
class Truck : Vehicle { }
But, in F# the following...
[<XmlInclude(typeof<Car>)>]
[<XmlInclude(typeof<Truck>)>]
type Vehicle() = class end
type Car() = inherit Vehicle()
type Truck() = inherit Car()
...results in a compiler error: This is not a constant expression or valid custom attribute value.
You should address a circular type dependency introduced by forward usage of types in attributes. The snippet below shows how this can be done in F#:
// Compiles OK
[<AttributeUsage(AttributeTargets.All, AllowMultiple=true)>]
type XmlInclude(t:System.Type) =
inherit System.Attribute()
[<XmlInclude(typeof<Car>)>]
[<XmlInclude(typeof<Truck>)>]
type Vehicle() = class end
and Car() = inherit Vehicle()
and Truck() = inherit Car()
Can you try putting together a more complete example that gives the error? I just quickly tried something similar and it works fine (in F# 3.0 in Visual Studio 2012):
type Car = C
type XmlInclude(typ:System.Type) =
inherit System.Attribute()
[<XmlInclude(typeof<Car>)>]
let foo = 0
I guess there is some tiny detail somewhere that confuses the F# compiler for some reason - but it should understand typeof (which is, in reality, a function) and allow its use in attributes.

Casting to types that are know only at Runtime by their string names. C#

I've got a problem here. (C#)
There's a collection in another assembly (I cannot change it) that takes a string as parameter and returns an object.
Like:
object Value = ThatCollection.GetValue("ParameterName");
The problem is, for each parameter string, it returns a DIFFERENT type as object.
What I want is to cast those objects to their respective types, knowing the types only at runtime by their string names.
I need to do some operations with those returned values.
And for that I need to cast them properly in order to access their members and so.
Limitations:
I cannot use "dynamic" since my code needs to be done in an older framework: 3.5 (because of interop issues).
I need to do operations with MANY returned values of different types (no common interfaces nor base classes, except "object", of course)
All I have is a table (containing string values) correlating the parameter names with their returned types.
Yes, I could transform that table into a biiig "switch" statement, not very nice, don't want that.
Any hints??
You want to look into reflection, something like the following should work to cast an object to type T. Set up a simple cast method:
public static T CastToType<T>(object o)
{
return (T)o;
}
Invoke this using reflection:
Type t = Type.GetType(stringName)
MethodInfo castTypeMethod = this.GetType().GetMethod("CastToType").MakeGenericMethod(t);
object castedObject = castTypeMethod .Invoke(null, new object[] { obj });

Groovy type conversion

In Groovy you can do surprising type conversions using either the as operator or the asType method. Examples include
Short s = new Integer(6) as Short
List collection = new HashSet().asType(List)
I'm surprised that I can convert from an Integer to a Short and from a Set to a List, because there is no "is a" relationship between these types, although they do share a common ancestor.
For example, the following code is equivalent to the Integer/Short example in terms of the
relationship between the types involved in the conversion
class Parent {}
class Child1 extends Parent {}
class Child2 extends Parent {}
def c = new Child1() as Child2
But of course this example fails. What exactly are the type conversion rules behind the as operator and the asType method?
I believe the default asType behaviour can be found in: org.codehaus.groovy.runtime.DefaultGroovyMethods.java
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.java.
Starting from DefaultGroovyMethods it is quite easy to follow the behavior of asType for a specific object type and requested type combination.
According to what Ruben has already pointed out the end result of:
Set collection = new HashSet().asType(List)
is
Set collection = new ArrayList( new HashSet() )
The asType method recognizes you are wanting a List and being the fact HashSet is a Collection, it just uses ArrayList's constructor which takes a Collection.
As for the numbers one, it converts the Integer into a Number, then calls the shortValue method.
I didn't realize there was so much logic in converting references/values like this, my sincere gratitude to Ruben for pointing out the source, I'll be making quite a few blog posts over this topic.

Resources