ArgumentError: First argument to `@sprintf` must be a format string

julia> using Printf

julia> @sprintf("%.2f", 3.14159)
"3.14"

julia> @sprintf("%."*"3"*"f", 3.14159)
ERROR: ArgumentError: First argument to `@sprintf` must be a format string.

julia> format_str = "%.2f"
"%.2f"

julia> @sprintf(format_str, 3.14159)
ERROR: ArgumentError: First argument to `@sprintf` must be a format string.

Then how to write a function that returns a formatted string such as:

function fun(digits, num)
    return @sprintf("%." * string(digits) * "f", num)
end
julia> using Printf

julia> function fun(digits::Integer, num::Real)
           fmtstr = "%." * string(digits) * "f"
           fmt = Printf.Format(fmtstr)
           return Printf.format(fmt, num)
       end
fun (generic function with 1 method)

julia> fun(3, π)
"3.142"

julia> fun(10, π)
"3.1415926536"
2 Likes

Thanks!!! But, why can’t the format string be replaced by a format_str?

@sprintf needs a string literal (not just a variable whose value is a string, but an actual typed-in string), because the macro expands when Julia first reads the code, and generates the Format object then. This is efficient, since it only happens once (not every time your function is called). However, it is incompatible with the formatting being dynamic.

Using the function API instead of the macro API as @fatteneder showed allows you construct the Format object dynamically (but it will happen every time that code runs).

I think the error message here could be clearer, since “must be a format string” doesn’t quite point to the issue.

4 Likes

Oh, I see. Many thanks! :handshake: :handshake:

1 Like