Julia @evalpoly宏与varargs

Mik*_*son 12 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()

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

julia> @evalpoly(0.5, c...)
ERROR: BoundsError()
Run Code Online (Sandbox Code Playgroud)

有人能指出我正确的方向吗?

看到这个问题的好答案后添加

在我玩这些答案之前,我还没有看到过一个微妙的东西.该z参数@evalpoly可以是一个变量,但系数预计将文字

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
Run Code Online (Sandbox Code Playgroud)

查看最后一个命令的扩展输出,可以看出确实是这样的情况,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)
Run Code Online (Sandbox Code Playgroud)

Iai*_*ing 8

我不相信你想要做的事情是可能的,因为它@evalpoly是一个宏 - 这意味着它在编译时生成代码.它产生的是Horner方法的非常有效的实现(在实数情况下),但是这样做需要知道多项式的程度.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
Run Code Online (Sandbox Code Playgroud)

正变成

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
Run Code Online (Sandbox Code Playgroud)

除了,不是这样,因为它使用Horners统治,但无论如何.问题是,在不知道系数的数量的情况下,它不能在编译时生成该表达式.但它不需要知道什么z是根本.


Eri*_*ter 7

Julia中的宏应用于他们的参数.要使其工作,您需要确保c@evalpoly评估之前进行扩展.这有效:

function f()
    c=[1,2,3,4]
    @eval @evalpoly 0.5 $(c...)
end
Run Code Online (Sandbox Code Playgroud)

在这里,@eval评估其论点,并进行扩展$(c...).后来@evalpoly看到五个论点.

如上所述,这可能效率不高,因为@eval每次f调用函数时都会调用它.您需要将调用移到@eval函数定义之外:

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

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


Mat*_* B. 5

@evalpoly埃里克和伊恩在解释为什么不起作用以及如何强制它起作用方面做得很好。然而,如果您只想评估多项式,最简单的解决方案可能就是使用Polynomials.jl

julia> using Polynomials
       c = [1,2,3,4]
       polyval(Poly(c), 0.5)
3.25
Run Code Online (Sandbox Code Playgroud)