Julia宏无法识别数组参数

时间:2017-01-20 00:28:57

标签: julia

我编写了一个相当复杂的宏来操作数组,但它没有用。即使用一些非常简单的东西替换我的宏,我也会收到相同的错误消息:

macro len(arr::Array)
    length(arr)
end

@len [1 2 3]

我得到的错误信息是:

ERROR: LoadError: MethodError: no method matching @len(::Expr)

为什么朱莉娅坚持将我的输入解释为表达式?我对Julia完全不熟悉,显然我对宏或类型系统都不了解。有人可以解释一下吗?

编辑:时间来解释我的原始宏是什么。我想将表作为输入并使用它来定义本地范围中的变量 。第一列中的条目定义单个变量名称,其他列定义变量内容。由于函数不能这样做,我需要一个宏。我有一个工作宏,它将一个长(三引号)字符串作为输入,但现在我希望它将数组作为输入。

在解释之后,也许我应该添加另一个子问题:为什么我的其他宏接受适当的输入(它被定义为macro foo(text::String))而数组版本没有?

3 个答案:

答案 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 RackauckasIsaiah指出)。我被自己的实验误导了,因为类似的字符串宏会起作用:

# 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])"