簡體   English   中英

在使用haxe宏構建的函數中使用局部變量

[英]Using local variables in function built with haxe macro

我有一個LangBuilder宏類; 它用於構建langObjects:Map<String, Dynamic>在編譯時以各種語言langObjects:Map<String, Dynamic>文本langObjects:Map<String, Dynamic> ,並通過@:build宏在類中注入此結構。 地圖的每個項目都包含支持的每種語言的字段。 結果是:

@:build(LangBuilder.build())
class Lang{}

trace(Lang.langObjects["hello-world"].en); //outputs "Hello World!"
trace(Lang.langObjects["hello-world"].it); //outputs "Ciao Mondo!"

這非常有效,但我想我可以使用函數getLangText隱藏langObjects結構,其中包含文本id(例如"hello-world" )和語言代碼(例如"it" )的參數。

所以我試圖將這個函數添加到類中:

public static function getLangText(id:String, lang:String)

其非宏版本可表示為:

public static function getLangText(id:String, lang:String){
    var _langObj_id = langObjects[id];
    switch(lang){
        case "it":
            return _langObj_id.it;
        case "en":
            return _langObj_id.en;
    }
    return "Missing Translation";

如果我使用此代碼將此函數轉換為宏:

var code = macro {
  var _langObj_id = langObjects[$i{"id"}];
  switch($i{"lang"}){
    case "it":
      return _langObj_id.it;
    case "en":
      return _langObj_id.en;
  }
  return "Missing translation";
};

var myFunc:Function = {
  args: [{
    name: "id",
    type: TPath({name: "String", pack: []}),
    meta: null
  },
  {
    name: "lang",
    type: TPath({name: "String", pack: []}),
    meta: null
  }],
  ret: (macro:String),
  expr: macro $code
};

fields.push({
  pos: Context.currentPos(),
  name: "getLangText",
  meta: null,
  kind: FieldType.FFun(myFunc),
  doc: null,
  access: [Access.APublic, Access.AStatic]
});

......它沒有問題。 但是我想知道如何在沒有switch情況下編寫它,使其更靈活,並學習一些關於haxe宏的東西。 我已經看到了一些示例,其中可以使用$p{}或使用object.$fieldName在宏中訪問字段。 然而,haxe手冊警告第二種形式只能用於簡單的標識符; 例如object.${fieldName}不起作用。

所以我試試這段代碼:

var code = macro {
  var l:String = $i{"lang"};
  var _langObj_id = langObjects[$i{"id"}];
  return _langObj_id.$l;
};

編譯器出錯

未知標識符:l

在包含return _langObj_id.$l;

然后我嘗試使用$p{}具體化:

var code = macro {
  var _langObj_id = langObjects[$i{"id"}];
  return macro $p{["_langObj_id", $i{"lang"}]};
};

但錯誤類似:

未知標識符:lang

我肯定可以將langObjects結構更改為Map<String, Map<String, String>> ,然后將代碼更改為:

var code = macro {
  return macro langObjects[$i{"id"}][$i{"lang"}];
};

我認為這會有效,但現在我試圖理解為什么_langObj_id.$lang$p{["_langObj_id", $i{"lang"}]}都不起作用,以及正確的方法是什么在這種情況下訪問一個字段。

在compile- / macro-time時不知道lang參數的值,所以我看不出如何生成像langObjects["mytext"].en這樣的字段訪問表達式。 在運行時,實際調用getLangText()時, lang可以是"en" ,或其他任何東西。 因此,仍然需要一個switch-case,if-else-chain或反射來處理所有可能的值。

如果不使用由構建宏創建的getLangText()是表達式宏/ macro function ,則函數調用將在編譯時進行求值,並替換為它返回的表達式。 這將允許您根據參數生成適當的字段訪問表達式。 它可能看起來像這樣:

class Macro {
    public static var langObjects = ["mytext" => {en: "hello", de: "hallo"}];

    public static macro function getLangText(id:String, lang:String) {
        return macro {
            var langObject = Macro.langObjects[$v{id}];
            langObject.$lang;
        }
    }
}
class Main {
    static function main() {
        trace(Macro.getLangText("mytext", "en"));
        trace(Macro.getLangText("mytext", "de"));
    }
}

在JS目標上編譯如下:

Main.main = function() {
    var langObject = Macro.langObjects.get("mytext");
    console.log("source/Main.hx:3:",langObject.en);
    var langObject1 = Macro.langObjects.get("mytext");
    console.log("source/Main.hx:4:",langObject1.de);
};

也許這就是你要找的東西? 很難說不知道你想要解決什么問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM