Open utterances-bot opened 6 years ago
The solution provided above is for compile-time types. In case you need a solution for Anonymous, run-time structuress (such as those created from JSON objects), one can be built via the Reflect package like this:
function merge(base: Dynamic, ext: Dynamic) {
var res = Reflect.copy(base);
for(f in Reflect.fields(ext)) Reflect.setField(res,f,Reflect.field(res,f));
return res;
}
@velochy The difference between the article and your solution is that the former remains type-safe, where yours is dynamic. The other difference is that the macros run at compile-time, and yours run-time. That means that with the macro based solution, the compiler can still provide auto-completion etc and there is less run-time overhead.
For all Haxe targets, macros are supported, since they run when the code is compiling.
Do you have a minimal example where this leads to null pointer exceptions? cc @AdrianV
@markknol yes, I think the solution I propose solves a similar but fundamentally different problem: that of dynamic, run time structures (such as those parsed from JSON) where we do not have proper type definitions available at compile time so this could not be done via macros. So, this was in no way meant to invalidate your snippet but rather provide a quick reference for those who found your post while looking for a solution to a slightly different problem with rather similar search keywords.
Edited my original reply to reflect this better.
There's probably something else wrong if you don't know your own JSON structure though.
The example above doesn't do a deep merge. What would need to be updated to do a deep merge?
@zabojad Current code and your proposal with one with deep merge would be awesome in a library, Does somebody knows if such library (with APIs for objects) exists ?
@markknol, @velochy As somebody point it out in https://github.com/HaxeFoundation/haxe.org-comments/issues/20#issuecomment-510359544 seems that Using Reflect is considerable slow in general and should be avoided for these kind of uses. A comparison between this, a native Object.assign JS or similar API call and a solution using Reflect would be awesome. BTW this is another Reflect based implementation https://github.com/HaxeFoundation/haxe.org-comments/issues/20#issuecomment-510357667
@AdrianV Could you please give some details on this line case TAnonymous(_.get() => tr):
, particularly what's the _
and where can I find info on its signature?. I think it understand what it is more or less but I want to know what other things can I do with it.
Also, on this kind of macros that create an instance method, do you know how can I access the name of the variable in the method call statement. In this case, foo.combine(bar)
how can I obtain the name 'foo' from inside the macro (I needed to generate code) ?
Thanks!
@cancerberoSgx You might want to look into pattern matching to figure out what the syntax does https://code.haxe.org/category/beginner/pattern-matching.html
I found there are some problem when the structures use JSON-like syntax and key of them contains Haxe-keywords:
var obj = {a: 1, "var": "test"};
trace(Json.stringify(obj));
// {"a":1,"var":"test"}
trace(Json.stringify(StructureCombiner.combine(obj, {b: 2})));
// {"b":2,"a":1} // the field of "var" is missing
I need help that is it works as expected, and is there anyway to avoid the problem?
Take a look for the online example.
@zhengxiaoyao0716 Documentation says
While any string literal is allowed, the field is only considered part of the type if it is a valid Haxe identifier.
Combine two or more structures - Macros - Haxe programming language cookbook
Haxe makes it easy to define extensions for a typedef, but there is no easy way to combine the values of two or more structures to one, like {a:2} and {b:foo} to {a:2,b:foo}. The following macro does this for you.
https://code.haxe.org/category/macros/combine-objects.html