Some queries about macro Horner

In Macros for numerical performance: Horner’s methodhttps://github.com/stevengj/18S096-iap17/blob/master/lecture4/Metaprogramming.ipynb, macro hornor is defined as follows:

copied from base/math.jl

macro horner(x, p...)
    ex = esc(p[end])
    for i = length(p)-1:-1:1
        ex = :( $(esc(p[i])) + t * $ex )
    end
    Expr(:block, :(t = $(esc(x))), ex)
end

so why use a new variable t in for loop, and after the loop still use Expr(...), not just defined the hornor as follows:

macro horner2(x, p...)
    ex = esc(p[end])
    for i = length(p)-1:-1:1
        ex = :( $(esc(p[i])) + x * $ex )
    end
    ex
end

3

Try replacing x with an expression, and you’ll see that horner2 re-computes that expression every time instead of re-using its value (you’re also missing an $(esc(x)) in your code):

julia> macro horner2(x, p...)
           ex = esc(p[end])
           for i = length(p)-1:-1:1
               ex = :( $(esc(p[i])) + $(esc(x)) * $ex )
           end
           ex
       end
@horner2 (macro with 1 method)

julia> macroexpand(:(@horner2(expensive_function(), 2, 3, 4)))
:(2 + expensive_function() * (3 + expensive_function() * 4))

compare with:

julia> macroexpand(:(@horner(expensive_function(), 2, 3, 4)))
quote
    #2#t = expensive_function()
    2 + #2#t * (3 + #2#t * 4)
end
6 Likes

wow, thank you very much!