巨集像是乙個函式,這個函式接受一組引數返回乙個表示式。
乙個簡單的巨集定義:
julia> macro sayhello(name)
return :( println("hello, ", $name) )
end@sayhello (macro with 1 method)
這個巨集接收乙個引數並返回乙個表示式列印一句話,呼叫:
julia> @sayhello("human")
hello, human
1、巨集呼叫兩種呼叫方式
@name expr1 expr2 ...
@name(expr1, expr2, ...)
注意第二種與下面帶空格的呼叫的區別,下面的呼叫表示傳乙個引數,這個引數是乙個元組;而上面第二種呼叫表示傳遞多個引數以逗號分隔:
@name (expr1, expr2, ...)
1)陣列做引數
@name[a b] * v
@name([a b]) * v
注意和下面的區別,上面表示陣列做[a b]引數呼叫巨集然後乘以v ,下面的表示陣列[a b]先和v相乘,結果作為巨集的引數:
@name [a b] * v
2)巨集除了手動傳遞的引數外,還有隱含傳遞的引數__source__ 和 __module__,__source__提供的巨集呼叫的位置資訊,用於排查錯誤;如圖:
2、構造高階巨集下面定義乙個簡單的巨集@assert,這個巨集用來判斷傳入表示式的值,如果是true返回nothing,否則報錯。
note:報錯資訊是將傳入的表示式轉換成字串,這個無法用函式實現。
julia> macro assert(ex)
return :( $ex ? nothing : throw(assertionerror($(string(ex)))) )
end@assert (macro with 1 method)
這樣呼叫:
julia> @assert 1 == 1.0
julia> @assert 1 == 0
error: assertionerror: 1 == 0
上面的呼叫等同於下面的表示式:
1 == 1.0 ? nothing : throw(assertionerror("1 == 1.0"))
1 == 0 ? nothing : throw(assertionerror("1 == 0"))
下面我們把巨集擴充套件一下,使其有乙個傳入報錯資訊的引數:
julia> macro assert(ex, msgs...)
msg_body = isempty(msgs) ? ex : msgs[1]
msg = string(msg_body)
return :($ex ? nothing : throw(assertionerror($msg)))
end@assert (macro with 1 method)
注意:巨集也是乙個函式,所以巨集可以有多個方法,如下面的巨集有兩個方法:
julia> macro assert(ex)
return :( $ex ? nothing : throw(assertionerror($(string(ex)))) )
end@assert (macro with 2 methods)
使用@macroexpand檢視巨集擴充套件後的結果:
julia> @macroexpand @assert a == b
:(if main.a == main.b
main.nothing
else
(main.throw)((main.assertionerror)("a == b"))
end)
Julia 元程式設計 巨集
元程式設計 鼻祖是lisp 一直在語法上和書寫上特立獨行,其功能也和一般的函式不一樣,與從不同。這個你需要去體會。比如反射。有人喜歡 用程式生成程式 等描述。比如,沒有事先定義乙個類或函式,但是可以根據客戶輸入的資訊,動態生成相應的類或函式。這個有點象c 的 模版 比如,你輸入引數input nam...
巨集元程式設計 技術 auto rec
auto rec巨集會快速探測滿足探測謂詞條件的 序號 最小的巨集。如果滿足條件會走實線深度往下探測,當遇到不滿足條件會走虛線。下面以探測16以內的 序號 define tl node 16 p tl if p 16 tl node 8,tl node 24 define tl node 8 p t...
C語言程式設計 學習筆記 巨集定義
編譯預處理指令 開頭的是編譯預處理指令 它們不是c語言的成分,但是c語言程式離不開它們 define用來定義乙個巨集 如 define pi 3.14159這樣pi這個東西就是3.14159的值 在編譯過程中,計算機會把 中出現的pi全部換成3.14159 也可以有如下定義 define forma...