Extern Array<T> class
RealyUniqueName opened this issue · comments
First of all: Real nice effort @RealyUniqueName and great work so far!
As this is is the top issue ATM I'll start with arrays here.
My ideas concerning arrays:
- IMO
Array<T>
should remain a wrapper class in haxe because native PHP arrays behave very differently from haxe arrays. A direct extern is not a good idea. Also there are indexed and associative arrays which map to different things in haxe. - I would introduce something like
NativeArrayI<T>
(indexed) andNativeArrayA<T>
(associative) as abstracts (and an underlying @:coreType abstract NativeArray), so haxe arrays/structs/maps can be auto-cast to and from native php arrays. I wrote some macro code for this once, which worked pretty good.
Especially associative arrays are mostly used like structs in PHP for passing options e.g.
So you would be able to do this in a typed manner:
var opt:NativeArrayA<{prop1:String, prop2:Int}> = {prop1: "foo", prop2: 2};
var arr:NativeArrayI<Int> = [1, 2, 3];
generates:
$opt = array('prop1' => "foo", 'prop2' => 2);
$arr = array(1, 2, 3);
So it should be possible to use native arrays, but only when explicitly declared.
Good point. And yet i wish we can use native php arrays for Array<T>
. It's a huge performance boost especially in terms of JSON parsing/encoding.
Maybe we can prohibit implicit Array<T> <-> NativeArray
parsing to make sure thrid party php code will not affect haxe-generated one?
Consider this. e.g.:
[1, 2, 3] == [1, 2, 3]
PHP: true, Haxe: false.
Hmm... This one leaves no option :)
Be prepared for other surprises :-) This dynamic stuff is extremely terrible.
Also I think a light wrapper Array class with inlined array functions where possible should be not so expensive in terms of performance. And some clever abstracts can give you native array access if needed. Just my 2 cents of course...
Having a wrapper class works fine while in haxe context, but creates terrible situations when interfacing with native php code. I'd happily work around some edge cases if that means being able to pass arrays along without a conversion step. Having the NativeArray classes doesn't really help when trying to write cross platform code, as it restricts your target to php.
I guess everyone has different use cases...
Having the NativeArray classes doesn't really help when trying to write cross platform code
Of course not. For cross-platform code use Array. It should be a light as possible wrapper to make it work cross-platform.
A lot of targets have an additional NativeArray class, that's not without a reason.
Also [1, 2, 3] == [1, 2, 3]
is no edge case, this is general array behaviour (a.k.a. PHP weirdness)
What I mean is.. I like to use and write cross platform haxe code. Which means I'll be using Array. Which also means any native php code interfacing with my code will need to have any array passed in converted to the wrapper. And another conversion to a native array if the return value is an array as well. And a check to see if I'm calling the method from the haxe or php side, because an array which is already wrapped doesn't need to be wrapped another time. Which means any public facing method which could be used from php needs a lot of conversion. I've implemented this as a macro solution in my current codebase, but it's something which I would ideally like to scrap completely. There's too many things which can slip through the cracks, and the conversion steps just don't feel right. I could use some NativeArray solution but that just means the conversion would be done elsewhere, as any general haxe lib will be using Array.
The equality might not be an edge case. I just can't recall ever trying to check equality on arrays - hence I did not even know the behaviour of either haxe or php.
I think I just feel a bit too strong on this subject, so I better refrain from further discussion :) I'll leave this up to you guys.
Which also means any native php code interfacing with my code will need to have any array passed in converted to the wrapper. And another conversion to a native array if the return value is an array as well.
More or less, yes, that's the cost of cross-platform.
And a check to see if I'm calling the method from the haxe or php side, because an array which is already wrapped doesn't need to be wrapped another time. Which means any public facing method which could be used from php needs a lot of conversion.
I don't understand. Consider an abstract NativeArrayI which auto-casts to and from the underlying php array. You'd do:
var arr1 = [1,2,3]; //haxe Array<Int>;
var arr2:Array<String> = PhpInterface.nativeCall(arr1); // auto-wraps and unwraps native array
// php interface:
extern PhpInterface {
function nativeCall(arr:NativeArrayI<Int>):NativeArrayI<String>;
}
which would generate (more or less):
$arr2 = new _hx_array(PhpInterface::nativeCall($arr1->a));
It's just a matter of the right interface definitions (native types on the PHP side, haxe types on the haxe side), no?
Additionally I added a macro @:from
call that translates literal [1,2,3]
to array(1,2,3)
, so no wrapper at all in this case (when you call PhpInterface.nativeCall([1,2,3])
)
I think I just feel a bit too strong on this subject, so I better refrain from further discussion
Actually I had this idea as well, using native array directly...
I'm using it mostly the other way around. Exposing my haxe classes for use in php. But you're right I might be able to ease the situation with an abstract over NativeArray whith a @:to
array. In any case I'll revisit that implementation once this new target is finished.
I'm using it mostly the other way around. Exposing my haxe classes for use in php.
This should work just the same. You'd have a haxe function expecting a NativeArray from PHP, which is automatically wrapped and returning a NativeArray to PHP (the haxe array unwrapped).
But you're right I might be able to ease the situation with an abstract over NativeArray whith a @:to array.
You'll need @:from as well for bidirectional communication. I'll put my implementation on github later this week. It's pretty cool for associative arrays as well, which get cast to structs in haxe.