#
# dontimes.boo
#
import System
import Boo.Lang.Compiler
macro DoNTimes:
n = DoNTimes.Arguments[0] as Ast.IntegerLiteralExpression
print n.GetType().ToString() # n is IntegerLiteralExpression
print DoNTimes.Body.GetType().ToString() # DoNTimes.Body is Block
blocks = Ast.Block() # create new block add DoNTimes.Body n times.
for i in range(Convert.ToInt32(n.ValueObject)):
blocks.Add( DoNTimes.Body )
return blocks
DoNTimes 3:
print "foo"
print "Press any key to continue . . . "
Console.ReadKey(true)
使用 booi 來執行,你會看到下面的訊息,foo 被印了三次:
Boo.Lang.Compiler.Ast.IntegerLiteralExpression
Boo.Lang.Compiler.Ast.Block
foo
foo
foo
Press any key to continue . . .
那這跟用 for 迴圈來跑有什麼不同?
首先用 booc 來編譯:booc -t:exe dontimes.boo,在編譯的時候,你會發現第9行跟第10行的訊息被印了出來:
Boo.Lang.Compiler.Ast.IntegerLiteralExpression
Boo.Lang.Compiler.Ast.Block
這證明了 boo compiler 會在編譯時,把 macro 的部份先拿出來編譯,然後在編譯的時後去執行 macro,對程式碼進行替換。然後你會發現執行 dontimes 的時候,只印了 foo 三次。
用 reflector 來看,可以看到:
private static void Main(string[] argv)
{
Console.WriteLine("foo");
Console.WriteLine("foo");
Console.WriteLine("foo");
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey(true);
}
代碼只有三行Console.WriteLine("foo");,這很清楚的說明了 booc 在編譯時,就把 macro 的內容替換進去了。
沒有留言:
張貼留言