HaxeFoundation / haxe.org-comments

Repository to collect comments of our haxe.org websites
2 stars 2 forks source link

[code.haxe.org] Macros - Combine two or more structures #1

Open utterances-bot opened 6 years ago

utterances-bot commented 6 years ago

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

velochy commented 5 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;
  }
markknol commented 5 years ago

@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

velochy commented 5 years ago

@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.

Simn commented 5 years ago

There's probably something else wrong if you don't know your own JSON structure though.

zabojad commented 5 years ago

The example above doesn't do a deep merge. What would need to be updated to do a deep merge?

cancerberoSgx commented 5 years ago

@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

cancerberoSgx commented 5 years ago

@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!

markknol commented 5 years ago

@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

sonygod commented 3 years ago

haxe 4.1.5

https://github.com/hkssprangers/hkssprangers/blob/c39c5a8a58730c00095367fff9a5b3e9543c200a/src/hkssprangers/ObjectTools.hx

zhengxiaoyao0716 commented 2 years ago

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.

alexeychikk commented 1 year ago

@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.

https://haxe.org/manual/types-structure-json.html