Understanding Macro


#1

I struggle to wrap my skull around metaprogramming!

So, following great advice (thanks guys) [Extract intermediate data from inside a function] I have written the following code

#module spying
#export spy
#export store
# a simple spying closure
function spy(targets)
    vals=[]
    tags=[]
    function store(val,tag)
        if tag ∈ targets
            push!(vals,copy(val))
            push!(tags,tag)
        end
    end
    store(val)=store(val,:unspecified)
    function get()
        return (vals,tags)  
    end
    return store,get
end

macro store(ex)
    @assert ex.head== :(=)
    local var = ex.args[1]
    return quote
        $ex
        store($var,var)
    end
end
#end #module spying

#using spying
# a function to spy on
f(x) = f((val,tag)->nothing,x)
function f(store,x)
    y = x
    for i = 1:3
        @store y = 3*y
        #y = 3*y
        #store(y,:y)
    end
    z = y+2
    store(z,:z)
    return 2z
end

(store,results)=spy([:y,:z])
f(store,3)
(vals,tags)=results()

display(vals)
display(tags)

The idea is to be able to extract intermediate results from function f, by spending in a function to retrieve the data. Any way, if, int he definition of f I comment the line with a macro, and uncomment the two following lines, everything works like a breeze. But my “macro store” is not doing what I want.

a) Executing the code generated by the call @store y = 3*y generates a “y not defined” error. But the code @store y = 3 does not generate this error.
b) I want the macro to generate the code store(y,:y) and I do not know how to generate :y

: )

Philippe


#2

I think this is what you want:

julia> macro store(ex)
           @assert ex.head== :(=)
           local var = ex.args[1]
           return quote
               $(esc(ex))
               store($(esc(var)), $(Meta.quot(var)))
           end
       end
@store (macro with 1 method)

julia> @macroexpand @store y = 3*y
quote
    #= REPL[18]:5 =#
    y = 3y
    #= REPL[18]:6 =#
    (Main.store)(y, :y)
end

You need to escape the ex, otherwise the y gets mangled. (Although I’m a bit surprised that the mangled name does not show up in the error).


#3

BINGO, you answered both questions. The “esc”, I should have known. The Meta.quot: well that was exotic!

:grinning: Thank you!