HaxeでluaのネイティブコードにArrayを公開するときの作法

ここで自分が質問してたことのまとめです。 https://github.com/HaxeFoundation/haxe/issues/9512

問題点

Arrayをluaのネイティブコードに向けて公開したとき、
Haxeは0-indexedなのに対し、luaは1-indexedなので、0番目の要素が(取り方によっては)取れない。

@:expose
class Sample {
    static function main(): Array<Int> {
        return [10, 20, 30];
    }
}
fromHaxe = require 'sample'

print('native')
local a = { 10, 20, 30 }
for i, m in ipairs(a) do
  print(string.format("%d: %s", i, m))
end

print('from haxe')
local b = fromHaxe.Sample.main()
for i, m in ipairs(b) do
  print(string.format("%d: %s", i, m))
end

実行すると、頭の10が失われていることが分かる。

haxe -main Sample -lua sample.lua && lua sample2.lua
native
1: 10
2: 20
3: 30
from haxe
1: 20
2: 30

解決策

luaと他言語でreturnを分ける

luaにはlua.Tableとして、他言語にはArrayとして公開する。

#if lua
return lua.Table.fromArray(data);
#else
return data;
#end

暗黙的な型変換を利用して勝手によしなにする

import lua.Table;
import lua.PairTools;

@:forward abstract LuaArray<T>(Table<Int, T>) from Table<Int, T> to Table<Int, T> {
  @:from static inline function fromArray<T>(array: Array<T>): LuaArray<T> {
    return Table.fromArray(array);
  }

  @:to function toArray(): Array<T> {
    final array = new Array<T>();
    PairTools.ipairsEach(this, function(index, element) {
      array.push(element);
    });
    return array;
  }
}
static function main2(): LuaArray<Int> {
  var data = [10, 20, 30]; // Array<int>
  return data;
}

疑問

Q

(標準ライブラリがLuaに対してArrayを返してくることに対して)
標準ライブラリは、NativeCodeで使いやすいインターフェイスであることが期待されているのではないですか?
また、そのあたりのポリシーが参照できるものはありますか?

A

Haxe全体としてのポリシーが参照出来るページなどはありません。
また、ターゲットによってメンテナが違うので見解やスタイルが異なることも考えられます。
歴史的な理由で変更できない、などの可能性もあります。