回答
使用解析變換可以得到足夠接近的結果。下面的parse_transform會在編譯時查找「atom1 ++ atom2」並將其轉換爲「atom1atom2」。
例如模塊
-module(z).
-export([z/0]).
-compile({parse_transform, zt}).
z() -> concat ++ enate.
用 'S' 編譯證明它是在編譯時確實級聯:
{function, z, 0, 2}.
{label,1}.
{func_info,{atom,z},{atom,z},0}.
{label,2}.
{move,{atom,concatenate},{x,0}}.
return.
按預期方式工作:包含
1> z:z().
concatenate
模塊解析變換:
-module(zt).
-export([parse_transform/2]).
parse_transform(AST, _Options) ->
[parse(T) || T <- AST].
parse({function, _, _, _, _} = T) ->
erl_syntax_lib:map(fun hashhash/1, T);
parse(T) -> T.
hashhash(Tree) ->
erl_syntax:revert(
case erl_syntax:type(Tree) of
infix_expr ->
Op = erl_syntax:infix_expr_operator(Tree),
Left = erl_syntax:infix_expr_left(Tree),
Right = erl_syntax:infix_expr_right(Tree),
case {erl_syntax:operator_name(Op), erl_syntax:type(Left), erl_syntax:type(Right)} of
{'++', atom, atom} ->
erl_syntax:atom(erl_syntax:atom_literal(Left) ++ erl_syntax:atom_literal(Right));
_ ->
Tree
end;
_ ->
Tree
end
).
編輯:編輯爲「超載」中綴++運算符。以前的版本使用'##'功能。
我認爲沒有。我認爲,因爲你可以做任何這些東西在運行時沒有副作用
據我所知,編譯器被認爲是非常好的,但怎麼會有沒有副作用(例如消耗的週期)? – jldupont 2009-09-14 18:48:39
你能舉例說明你的意思嗎? – 2009-09-14 21:29:36
我不知道我明白你在問什麼,但我會刺傷它。
-define(CATATOM(A, B), list_to_atom(list:concat(atom_to_list(A), atom_to_list(B)))).
AtomA = atom1.
AtomB = atom2.
NewAtom = ?CATATOM(AtomA, AtomB). % NewAtom is atom1atom2
或者你的意思是?
-define(CATATOM(A, B), AB).
NewAtom = ?CATATOM(atom1, atom2). % NewAtom is atom1atom2
雖然我不確定使用新的第二個實際是什麼。因爲只寫atom1atom2而不是宏會更簡單。
第二個將不會產生運行時副作用。第一個會產生運行時副作用,因爲宏的結果是3個函數在運行時運行。
有解析變換的概念,這將允許您在編譯時連接原子。
如果不解釋如何使用解析轉換來解決問題,那麼這對你並沒有什麼幫助。 – 2009-09-15 12:07:45
你實際上不可能做什麼都在一個宏裏面,它只是純粹的文本,很好的標記級別,替換。注:您正在處理源代碼並且未對其進行評估。如果你需要更復雜的替代類型,那麼你需要使用解析轉換。
如果你編寫了一個連接宏,你總是可以使用?? Arg形式來獲取作爲一個字符串的參數。查看在線參考手冊的預處理器部分。
當然,真正有趣的問題是爲什麼你想在編譯時連接兩個原子?我認爲這是另一個宏的輸出,否則就沒有意義了。
我希望能夠「參數化」模塊,例如 -define(APP,app)。 -define(EXT,ext)。 -define(NAME,?APP ++?EXT)。 運算符'++'將在編譯時連接兩個atom()。 – jldupont 2009-09-15 14:18:34
- 1. C#預處理器指令
- 2. 有沒有C++預處理指令的在線手冊?
- 3. 預處理指令導入基於對C#中的預處理指令平臺
- 4. C++預處理指令
- 5. objective-c預處理器指令
- 6. C#預處理器指令範圍
- 7. Gfortran預處理器指令
- 8. VB.NET預處理器指令
- 9. C++中的一行上有多個預處理器指令
- 10. 帶有預處理器指令的C++類世代
- 11. 爲什麼在預處理指令之後沒有分號?
- 12. 我沒有收到XSL處理指令!
- 13. 預處理器基於C
- 14. Lex規則的C預處理指令
- 15. C預處理指令(SQR-的Funktion)
- 16. Objective-C的預處理指令發出
- 17. 多行C預處理指令的宏
- 18. C++預處理指令限制
- 19. Unity預處理器指令錯誤?
- 20. xib中的預處理器指令?
- 21. 預處理器指令:#elif未定義?
- 22. 個人預處理器指令
- 23. 預處理器指令和#error
- 24. nuget庫中的預處理器指令
- 25. 腳本#預處理器指令?
- 26. 檢測iPad的預處理器指令
- 27. #elseif VS #elif指令(C/C++預處理器)
- 28. ##對於C(C++)預處理器有什麼意義?
- 29. 爲什麼有人會使用#if 1 C預處理器指令?
- 30. 在C#中的#if中使用#define預處理器指令是否有效#
這看起來不錯!我無法通過erlIDE來編譯它:我需要做一些特殊的事情嗎? – jldupont 2009-09-15 15:02:08
erlc在編譯z.erl時需要訪問zt.beam,因此您必須使用-pa標誌將其路徑添加到erlc中,最有可能的是:「erlc -pa。z.erl」。 不知道如何用erlIDE做到這一點。 – Zed 2009-09-15 15:50:53
erlIDE還沒有完整的功能...它不允許指定額外的路徑(例如與-pa開關)。 有沒有辦法做到這一點與編譯指令? – jldupont 2009-09-15 16:35:46