I edited my post. Seems to work. I don’t understand why this should not be possible. The call to @printf is just a transformation at parse time, so why not do the same with the additional now() call? Of course the new macro has the same restrictions as @sprintf.
julia> @myprintf("%.2f",1/9)
ERROR: LoadError: ArgumentError: @sprintf: first argument must be a format string
Stacktrace:
[1] @sprintf(::LineNumberNode, ::Module, ::Vararg{Any,N} where N) at /build/julia/src/julia-1.5.0/usr/share/julia/stdlib/v1.5/Printf/src/Printf.jl:1291
[2] run_repl(::REPL.AbstractREPL, ::Any; backend_on_current_task::Bool) at /build/julia/src/julia-1.5.0/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:292
[3] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia-1.5.0/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
in expression starting at REPL[42]:3
Otherwise if a user uses this macro in the context where they already have a variable called tmp_str it will be overwritten ! In my code it is bound to a new variable inside the let.
Since temp_str is not escaped you do not need the let. Local variables get renamed by default, and since temp_str is assigned to and not explicitly marked as global it is a local variable.
@chakravala, thanks! In fact, this is exactly how I implemented it now in production code, for all the reasons you mentioned. Initially, I put a variable just to be more explicit where the problem is. Now it is of course time to clean up.
Actually looks like I still run into a problem as above solution is not working in some very common scenario. Namely passing a variable into the macro (passing a number directly works)
import Printf.@sprintf;
import Dates.now;
macro myprintf(x, y...)
:(print(now(),":",@sprintf($x, $(esc(y))...)))
end
@myprintf("working %.f", 0.42)
#below fails with ERROR: MethodError: no method matching isfinite(::Symbol)
result = 0.43
@myprintf("failing %.f", result)
Thanks @simeonschaub! that indeed works as expected.
I wish somebody with a deep knowledge of macros would have written a bit deeper on the topic with tips and tricks, going into tricky situations like those
Yet, one more problem in this solution. using this macro inside a function seems to be not working
import Printf.@sprintf;
import Dates.now;
macro myprintf(x, y...)
:(print(now(), ":", @sprintf($x, $(esc.(y)...))))
end
function t()
r = 21
@myprintf("failing %.f\n", r * 2)
end
#calling function t is failing with unknown r
t()