The crux is that I want to build a string programmatically with a variable number of elements and can’t find a way to do it with @sprintf
julia> bnds = [1,2,3];
julia> @sprintf("%d,%d,%d,",bnds...)
"1,2,3,"
julia> repeat("%d,",3)
"%d,%d,%d,"
julia> @sprintf(repeat("%d,",3),bnds...)
ERROR: LoadError: MethodError: no method matching Printf.Format(::Expr)
Closest candidates are:
Printf.Format(::S, ::Vector{UnitRange{Int64}}, ::T) where {S, T} at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.7\Printf\src\Printf.jl:65
Printf.Format(::AbstractString) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.7\Printf\src\Printf.jl:81
Stacktrace:
[1] var"@sprintf"(__source__::LineNumberNode, __module__::Module, fmt::Any, args::Vararg{Any})
@ Printf C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.7\Printf\src\Printf.jl:895
in expression starting at REPL[29]:1
Yes. Because @sprintf
is a macro, it can only act on the string literal it’s given. It can’t generate code for repeat(...)
since the stuff repeat
does is handled at run-time, not parse-time. You can use a for
loop to do something similar, right? or map
and join
?
1 Like
But if I compute
fmt = repeat("%d,",3)
"%d,%d,%d,"
and pass the fmt
, which is a string, the error is the same.
Yes, I can create my final sting some other way but it looks clumsy.
lmiq
September 20, 2021, 5:14pm
4
alan
December 30, 2021, 9:18pm
6
This problem is more general than this thread suggests. It is not limited to repeated format items. Surely this is a bug:
julia> using Printf
julia> @sprintf (“aaa %d bbb”, 3)
“aaa 3 bbb”
julia> fmt = “aaa %d bbb”
“aaa %d bbb”
julia> @sprintf (fmt, 3)
ERROR: LoadError: MethodError: no method matching Printf.Format(::Symbol)
Closest candidates are:
Printf.Format(::S, ::Vector{UnitRange{Int64}}, ::T) where {S, T} at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Printf/src/Printf.jl:65
Printf.Format(::AbstractString) at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Printf/src/Printf.jl:81
Stacktrace:
[1] var"@sprintf "(source ::LineNumberNode, module ::Module, fmt::Any, args::Vararg{Any})
@ Printf /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Printf/src/Printf.jl:900
in expression starting at REPL[18]:1
alan:
Surely this is a bug
No, that’s how macros work: they replace expressions into other expressions. The @sprintf
macro expects as first argument a literal string, not a variable whose runtime value is a string: macros can’t possibly access runtime values of variables (unless you use tricks like @eval @sprintf($fmt, 3)
which gets the job done but defeats the purpose of using a macro in the first place).
5 Likes
jling
December 30, 2021, 9:28pm
8
what you want:
julia> fmt = "aaa %d bbb"
"aaa %d bbb"
julia> Printf.format(Printf.Format(fmt), 3)
"aaa 3 bbb"
3 Likes
alan
December 30, 2021, 10:02pm
9
Thank you.
I’m surprised no one has put that into a function called “sprintf”. It would be more useful than the macro.
2 Likes