我编写了一个相当复杂的宏来操作数组,但它没有用。即使用一些非常简单的东西替换我的宏,我也会收到相同的错误消息:
macro len(arr::Array)
length(arr)
end
@len [1 2 3]
我得到的错误信息是:
ERROR: LoadError: MethodError: no method matching @len(::Expr)
为什么朱莉娅坚持将我的输入解释为表达式?我对Julia完全不熟悉,显然我对宏或类型系统都不了解。有人可以解释一下吗?
编辑:时间来解释我的原始宏是什么。我想将表作为输入并使用它来定义本地范围中的变量 。第一列中的条目定义单个变量名称,其他列定义变量内容。由于函数不能这样做,我需要一个宏。我有一个工作宏,它将一个长(三引号)字符串作为输入,但现在我希望它将数组作为输入。
在解释之后,也许我应该添加另一个子问题:为什么我的其他宏接受适当的输入(它被定义为macro foo(text::String)
)而数组版本没有?
答案 0 :(得分:1)
用户Chris Rackauckas在与我讨论时回答了这个问题:
@len $a
宏是在表达式上,而不是在值上,所以
这听起来像你想要的功能
(如果真的需要的话)。
我不确定无论如何都能在那里工作。 这不是宏的用途.. 它主要用于将表达式转换为其他表达式。
如果您尝试在值上使用宏,则需要一个函数
(你可以@eval
或其他东西来使这个工作在这里工作,但是你会花很多时间让宏观行为像一个函数)
..作为一个功能:
julia> function len(x)
length(x)
end
len (generic function with 1 method)
julia> len(a)
3
julia> a
1x3 Array{Int64,2}:
1 2 3
答案 1 :(得分:1)
回答我自己的问题:这就是"荒谬的简单"应该写宏。
macro len(expr)
:(length($expr))
end
这适用于表达式,而非数组(感谢Chris Rackauckas和Isaiah指出)。我被自己的实验误导了,因为类似的字符串宏会起作用:
# MISLEADING CODE, DON'T USE THIS!
macro lenstr(str::String)
length(str)
end
显然Julia允许使用字符串宏,但这是宏对表达式进行操作的一般规则的例外。为了说明参数如何出现在宏中:
macro dump(arg)
dump(arg)
end
julia> @dump "foo bar"
String "foo bar"
julia> @dump [1,2,3]
Expr
head: Symbol vect
args: Array{Any}((3,))
1: Int64 1
2: Int64 2
3: Int64 3
typ: Any
julia> @dump [1 2 3]
Expr
head: Symbol hcat
args: Array{Any}((3,))
1: Int64 1
2: Int64 2
3: Int64 3
typ: Any
请注意宏如何将[1,2,3]
和[1 2 3]
视为表达式,而不是数组。这是我的错误的来源。通过应用这里学到的经验,我现在可以使用从数组创建局部范围变量的更复杂的宏。谢谢大家!
答案 2 :(得分:0)
带有嵌套宏的替代解决方案:
macro _localeval(ex)
esc(:($ex))
end
macro localeval(ex)
esc(@_localeval(Meta.parse(ex)))
end
@localeval "length([1 2 3])"