在使用 haxe 宏构建的函数中使用局部变量
Using local variables in function built with haxe macro
我有一个LangBuilder
宏class;它用于在编译时构建各种语言的langObjects:Map<String, Dynamic>
文本,并通过@:build
宏将此结构注入classes。 Map 的每个项目都有一个字段用于支持的每种语言。所以结果是:
@:build(LangBuilder.build())
class Lang{}
trace(Lang.langObjects["hello-world"].en); //outputs "Hello World!"
trace(Lang.langObjects["hello-world"].it); //outputs "Ciao Mondo!"
这非常有效,但我认为我可以使用函数 getLangText
和参数文本的 id(例如 "hello-world"
)来隐藏 langObjects
结构,并且语言代码(例如 "it"
)。
所以我正在尝试将此功能添加到 classes:
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;
};
编译器报错
Unknown identifier : l
在包含 return _langObj_id.$l;
.
的行上
然后我尝试使用 $p{}
具体化:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
return macro $p{["_langObj_id", $i{"lang"}]};
};
但错误类似:
Unknown identifier : 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"}]}
都行不通,以及访问字段的正确方法是什么那样的情况。
lang
参数的值在编译/宏时是未知的,所以我不知道如何生成像 langObjects["mytext"].en
这样的字段访问表达式。在实际调用 getLangText()
的运行时,lang
可能是 "en"
或其他任何内容。因此,这仍然需要一个 switch-case、if-else-chain 或反射来处理所有可能的值。
如果 using 不是由构建宏创建,而是 getLangText()
是表达式宏 / macro function
,函数调用将在编译时求值,并替换为表达式它 returns。这将允许您根据参数生成适当的字段访问表达式。它可能看起来像这样:
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);
};
也许这就是您要找的?不知道你要解决什么问题很难说。
我有一个LangBuilder
宏class;它用于在编译时构建各种语言的langObjects:Map<String, Dynamic>
文本,并通过@:build
宏将此结构注入classes。 Map 的每个项目都有一个字段用于支持的每种语言。所以结果是:
@:build(LangBuilder.build())
class Lang{}
trace(Lang.langObjects["hello-world"].en); //outputs "Hello World!"
trace(Lang.langObjects["hello-world"].it); //outputs "Ciao Mondo!"
这非常有效,但我认为我可以使用函数 getLangText
和参数文本的 id(例如 "hello-world"
)来隐藏 langObjects
结构,并且语言代码(例如 "it"
)。
所以我正在尝试将此功能添加到 classes:
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;
};
编译器报错
Unknown identifier : l
在包含 return _langObj_id.$l;
.
然后我尝试使用 $p{}
具体化:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
return macro $p{["_langObj_id", $i{"lang"}]};
};
但错误类似:
Unknown identifier : 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"}]}
都行不通,以及访问字段的正确方法是什么那样的情况。
lang
参数的值在编译/宏时是未知的,所以我不知道如何生成像 langObjects["mytext"].en
这样的字段访问表达式。在实际调用 getLangText()
的运行时,lang
可能是 "en"
或其他任何内容。因此,这仍然需要一个 switch-case、if-else-chain 或反射来处理所有可能的值。
如果 using 不是由构建宏创建,而是 getLangText()
是表达式宏 / macro function
,函数调用将在编译时求值,并替换为表达式它 returns。这将允许您根据参数生成适当的字段访问表达式。它可能看起来像这样:
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);
};
也许这就是您要找的?不知道你要解决什么问题很难说。