Interpolate @show macro

I want to interpolate the @show macro function.

For example.
I define a function

f(x) = x + 1

I want to see the behavior for different inputs:

julia> [@show f(x) for x = 1:3];
f(x) = 2
f(x) = 3
f(x) = 4

But what I really wanted to see is:

f(1) = 2
f(2) = 3
f(3) = 4

Trials
I tried to interpolate but:

julia> [@show f($x) for x = 1:3];
ERROR: syntax: "$" expression outside quote around show.jl:955
Stacktrace:
 [1] top-level scope
   @ REPL[186]:1

Then I tried quoting the expression but:

julia> [@show f(:($x)) for x=1:3];
f($(Expr(:quote, :($(Expr(:$, :x)))))) = 2
f($(Expr(:quote, :($(Expr(:$, :x)))))) = 3
f($(Expr(:quote, :($(Expr(:$, :x)))))) = 4

although

julia>  [println("f($(:($x)))") for x=1:3];
f(1)
f(2)
f(3)

Any suggestions ?

julia> f(x) = x + 1
f (generic function with 1 method)

julia> [@eval(@show(f($x))) for x = 1:3];
f(1) = 2
f(2) = 3
f(3) = 4

On my phone so can’t easily check but does something like

map(x-> @show f(x), collect(1:3))

Work?

the things you tried didn’t work because @show is a macro and print() takes the string after interpolation. Essentially, @show sees the expression itself, so if you have f(x), all @show can see is something like:

julia> Meta.@dump f(x)
Expr
  head: Symbol call
  args: Array{Any}((2,))
    1: Symbol f
    2: Symbol x

and it would simply print out this expression for you and print the result:

julia> @macroexpand @show f(x)
quote
    Base.println("f(x) = ", Base.repr(begin
                #= show.jl:1040 =#
                local var"#14#value" = f(x)
            end))
    var"#14#value"
end

it’s possible to make @show “understand” $ just like @btime, but it will be manual work because essentially $ is just another node in expression itself:


julia> Meta.@dump f($x)
Expr
  head: Symbol call
  args: Array{Any}((2,))
    1: Symbol f
    2: Expr
      head: Symbol $
      args: Array{Any}((1,))
        1: Symbol x
1 Like

didn’t work for me:

julia> map(x-> @show f(x), collect(1:3))
ERROR: MethodError: no method matching (::var"#5#6")()
Closest candidates are:
  (::var"#5#6")(::Any) at REPL[5]:1
Stacktrace:
 [1] map(f::var"#5#6")
   @ Base ./abstractarray.jl:2382
 [2] top-level scope
   @ REPL[5]:1

But [@eval @show f($x) for x=1:3] worked nicely. thanks! Also thanks for the explanation.

Macros are greedy, you may need parentheses to let them understand where they have to stop parsing, as I did above:

julia> map(x-> @show(f(x)), collect(1:3))
f(x) = 2
f(x) = 3
f(x) = 4
3-element Vector{Int64}:
 2
 3
 4

Of course, changing comprehension with map doesn’t change much in terms of what @show sees.

1 Like