宏像是一个函数,这个函数接受一组参数返回一个表达式。
一个简单的宏定义:数组
julia> macro sayhello(name) return :( println("Hello, ", $name) ) end @sayhello (macro with 1 method)
这个宏接收一个参数并返回一个表达式打印一句话,调用:函数
julia> @sayhello("human") Hello, human
一、宏调用spa
两种调用方式code
@name expr1 expr2 ... @name(expr1, expr2, ...)
注意第二种与下面带空格的调用的区别,下面的调用表示传一个参数,这个参数是一个元组;而上面第二种调用表示传递多个参数以逗号分隔:blog
@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__提供的宏调用的位置信息,用于排查错误;如图:string
二、构造高级宏it
下面定义一个简单的宏@assert,这个宏用来判断传入表达式的值,若是是true返回nothing,不然报错。
Note:报错信息是将传入的表达式转换成字符串,这个没法用函数实现。io
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)