Julia@evalpoly宏和varargs

Julia@evalpoly宏和varargs,julia,Julia,我正在尝试使用Julia的@evalpoly宏进行摸索。当我手动提供系数时,它可以工作,但我一直无法弄清楚如何通过数组提供这些系数 julia> VERSION v"0.3.5" julia> @evalpoly 0.5 1 2 3 4 3.25 julia> c = [1, 2, 3, 4] 4-element Array{Int64,1}: 1 2 3 4 julia> @evalpoly 0.5 c ERROR: BoundsError() jul

我正在尝试使用Julia的
@evalpoly
宏进行摸索。当我手动提供系数时,它可以工作,但我一直无法弄清楚如何通过数组提供这些系数

julia> VERSION
v"0.3.5"

julia> @evalpoly 0.5 1 2 3 4
3.25

julia> c = [1, 2, 3, 4]
4-element Array{Int64,1}: 
 1
 2
 3
 4

julia> @evalpoly 0.5 c
ERROR: BoundsError()

julia> @evalpoly 0.5 c...
ERROR: BoundsError()

julia> @evalpoly(0.5, c...)
ERROR: BoundsError()
有人能给我指出正确的方向吗

在看到这个问题的伟大答案后添加

有一个微妙之处是我在玩这些答案时才发现的。
@evalpoly
z
参数可以是变量,但系数应为文字

julia> z = 0.5
0.5

julia> @evalpoly z 1 2 3 4
3.25

julia> @evalpoly z c[1] c[2] c[3] c[4]
ERROR: c not defined
查看最后一个命令展开的输出,我们可以看到确实是这样的情况,z被分配给展开中的一个变量,但是系数被直接插入到代码中

julia> macroexpand(:@evalpoly z c[1] c[2] c[3] c[4])
:(if Base.Math.isa(z,Base.Math.Complex)
        #291#t = z
        #292#x = Base.Math.real(#291#t)
        #293#y = Base.Math.imag(#291#t)
        #294#r = Base.Math.+(#292#x,#292#x)
        #295#s = Base.Math.+(Base.Math.*(#292#x,#292#x),Base.Math.*(#293#y,#293#y))
        #296#a2 = c[4]
        #297#a1 = Base.Math.+(c[3],Base.Math.*(#294#r,#296#a2))
        #298#a0 = Base.Math.+(Base.Math.-(c[2],Base.Math.*(#295#s,#296#a2)),Base.Math.*(#294#r,#297#a1))
        Base.Math.+(Base.Math.*(#298#a0,#291#t),Base.Math.-(c[1],Base.Math.*(#295#s,#297#a1)))
    else 
        #299#t = z
        Base.Math.+(Base.Math.c[1],Base.Math.*(#299#t,Base.Math.+(Base.Math.c[2],Base.Math.*(#299#t,Base.Math.+(Base.Math.c[3],Base.Math.*(#299#t,Base.Math.c[4]))))))
    end)

我不相信您试图做的是可能的,因为
@evalpoly
是一个宏,这意味着它在编译时生成代码。它生成的是霍纳方法的一个非常有效的实现(在实数情况下),但要做到这一点,它需要知道多项式的次数。
c
的长度在编译时是未知的,因此它不起作用(也不能),而当您直接提供系数时,它就具备了所需的一切

但是错误消息不是很好,所以如果可以,您可以在Julia Github页面上提交一个问题

更新:对于问题的更新,是的,第一个参数可以是变量。你可以这样想:

function dostuff()
  z = 0.0
  # Do some stuff to z
  # Time to evaluate a polynomial!
  y = @evalpoly z 1 2 3 4
  return y
end
正在成为

function dostuff()
  z = 0.0
  # Do some stuff to z
  # Time to evaluate a polynomial!
  y = z + 2z^2 + 3z^3 + 4z^4
  return y
end

除了,不是那样,因为它使用霍纳斯法则,但不管怎样。问题是,如果不知道系数的数量,它无法在编译时生成表达式。但是它根本不需要知道
z
是什么。

Julia中的宏应用于它们的参数。为了实现这一点,您需要确保在计算
@evalpoly
之前展开
c
。这项工作:

function f()
    c=[1,2,3,4]
    @eval @evalpoly 0.5 $(c...)
end
在这里,
@eval
计算其参数,并展开
$(c…)
。稍后,
@evalpoly
将看到五个参数

如前所述,这可能没有效率,因为每次调用函数
f
时都会调用
@eval
。您需要将调用移动到函数定义之外的
@eval

c=[1,2,3,4]
@eval begin
    function f()
        @evalpoly 0.5 $(c...)
    end
end

当定义了
f
时,将调用
@eval
。显然,此时必须知道
c
。无论何时实际调用
f
,都不再使用
c
;它仅在定义
f
时使用。

Erik和Iain在解释
@evalpoly
为什么不起作用以及如何强制它起作用方面做了大量工作。但是,如果您只想计算多项式,最简单的解决方案可能就是使用:


将允许通过函数版本执行此操作。似乎它需要一些支持-添加一条评论,表达您希望在base中看到它的愿望!伊恩,谢谢你的洞察力。我当然很感激它,因为它帮助我大致了解Julia macros,而不仅仅是这个特定的问题。在接下来的几天里,我将尝试跟进您的建议,添加此问题。我已为您的更新更新了内容,请告诉我是否清楚。
julia> using Polynomials
       c = [1,2,3,4]
       polyval(Poly(c), 0.5)
3.25