# Using a variable to format printf not allowed?

**URL:** https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200
**Category:** New to Julia
**Tags:** pretty-printing
**Created:** [May 22, 2023, 8:08am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200 "2023-05-22T08:08:06Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)
#### Post date: [May 22, 2023, 8:08am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/1 "2023-05-22T08:08:06Z")

</div>

Hi!

I’m trying to write a simple text file where each line follows one of a few specific formats. Is it not permitted to use a variable to specify the format for `@printf`? Example:

```julia
julia> fname = "abc"
"abc"

julia> @printf("%s %s", "File name: ", fname)
File name: abc

```

works fine but the following does not work:

```julia
julia> fmt = "%s %s"
"%s %s"

julia> fname = "abc"
"abc"

julia> @printf(fmt, "File name: ", fname)
ERROR: MethodError: no method matching format(::String, ::Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{}}, ::String)
Closest candidates are:
  format(::IO, ::Printf.Format, ::Any...) at ~/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/share/julia/stdlib/v1.8/Printf/src/Printf.jl:820
  format(::Printf.Format, ::Any...) at ~/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/share/julia/stdlib/v1.8/Printf/src/Printf.jl:828
Stacktrace:
 [1] top-level scope
   @ REPL[41]:1

```

The same thing occurs with `@sprintf`. Thanks for clarifications on this matter.

---

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [May 22, 2023, 9:09am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/2 "2023-05-22T09:09:59Z")

</div>

A way to pass variable to `@printf` is to eval an interpolated expression:

```julia
julia> var = "%d";
julia> num = 10;
julia> eval(:(@printf($var, num)))
10

```

Note that:

```julia
julia> expr = :(@printf($var, num))
:(#= REPL[4]:1 =# @printf "%d" num)

```

It would have been more convenient to be able to pass variable, though.

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [May 22, 2023, 9:21am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/3 "2023-05-22T09:21:56Z")

</div>

```julia
julia> using Printf

julia> fmt = Printf.Format("%s %s")
Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{Printf.Spec{Val{'s'}}, Printf.Spec{Val{'s'}}}}(UInt8[0x25, 0x73, 0x20, 0x25, 0x73], UnitRange{Int64}[1:0, 3:3, 6:5], (%s, %s))

julia> fname = "abc"
"abc"

julia> Printf.format(fmt, "File name: ", fname)
"File name: abc"

```

---

<div class="post-metadata">

### Author: ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)
#### Post date: [May 22, 2023, 12:02pm UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/4 "2023-05-22T12:02:22Z")

</div>

Thanks a lot to both @Barget and @fatteneder.

Do you know where I can find the documentation for `Printf.Format` and `Printf.format`? Most URL links on the Internet lead to the page [Printf · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Printf/#man-printf) which does not say anything about the formats, or how this differs from `printf`… Thanks again.

---

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [May 22, 2023, 12:21pm UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/5 "2023-05-22T12:21:40Z")

</div>

You can find the documentation using the REPL, by triggering the help context (by typing `?`):

```julia
help?> Printf.Format
  Printf.Format(format_str)
[...]

```

Unfortunately, this is not put in Julia’s documentation, I assume because `Format` is not exported from `Printf` stdlib.

Once you’re used to Open Source world, you may take the habit to have a look at the source code. For instance, the `@printf` macro makes use of `Format`.

> <https://github.com/JuliaLang/julia/blob/672f609f97c8fb51ad7e8c7178b57c23972e2374/stdlib/Printf/src/Printf.jl#L1007>

… but admittedly, this would have been hard to guess 🙂

---

<div class="post-metadata">

### Author: ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)
#### Post date: [May 22, 2023, 12:25pm UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/6 "2023-05-22T12:25:18Z")

</div>

Thanks again, @Barget. While the Julia documentation is sometimes hard to decipher, I must say the community is really helpful!

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [May 22, 2023, 5:41pm UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/7 "2023-05-22T17:41:21Z")

</div>

> [@mmv](#):
>
> Do you know where I can find the documentation for `Printf.Format` and `Printf.format`? Most URL links on the Internet lead to the page [Printf · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Printf/#man-printf) which does not say anything about the formats, or how this differs from `printf`… Thanks again.

Like @Barget said, try the `?` operator:

```julia
help?> Printf.Format
  Printf.Format(format_str)

  Create a C printf-compatible format object that can be used for formatting values.

  The input format_str can include any valid format specifier character and modifiers.

  A Format object can be passed to Printf.format(f::Format, args...) to produce a formatted
  string, or Printf.format(io::IO, f::Format, args...) to print the formatted string directly
  to io.

  For convenience, the Printf.format"..." string macro form can be used for building a
  Printf.Format object at macro-expansion-time.

  │ Julia 1.6
  │
  │ Printf.Format requires Julia 1.6 or later.

```

---

<div class="post-metadata">

### Author: ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)
#### Post date: [May 23, 2023, 7:43am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/8 "2023-05-23T07:43:28Z")

</div>

Thanks @fatteneder. I’m currently able to print what I want with statements like

```julia
fmt3 = Printf.Format("%8s " * "%14d "^8 * "\n")

for cam = 1:misr_specs.ncameras
    Printf.format(out_stream, fmt3, misr_specs.camera_names[cam],
    stats[cam, 1], stats[cam, 2], stats[cam, 3], stats[cam, 4],
    stats[cam, 5], stats[cam, 6], stats[cam, 7], stats[cam, 8])
end

```

which works fine. However, I must still list each individual matrix element explicitly: statements like

```julia
Printf.format(out_stream, fmt3, misr_specs.camera_names[cam], stats[cam, :])

```

always generate an error message complaining about the mismatch between the format specification and the number of items to be printed. Yet, `stats[cam, :]` is a vector of 8 elements…

This works fine for small numbers of elements, but would be a chore (and look ugly) for dozens or hundreds of elements. I’ve tried to “explode” the vector into its components with `Tuple(stats[cam, :])`, or `x -> (x in stats[cam, :])`, or to use a vector notation in the format string itself, but that does not work either.

Any suggestion about how to iterate over the vector argument without having to list all its elements? Thanks again.

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [May 23, 2023, 8:04am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/9 "2023-05-23T08:04:29Z")

</div>

Maybe try splatting the arguments with `...`, e.g.

```julia
julia> using Printf

julia> fmt = Printf.Format("%d %d %d")
Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{Printf.Spec{Val{'d'}}, Printf.Spec{Val{'d'}}, Printf.Spec{Val{'d'}}}}(UInt8[0x25, 0x64, 0x20, 0x25, 0x64, 0x20, 0x25, 0x64], UnitRange{Int64}[1:0, 3:3, 6:6, 9:8], (%.0d, %.0d, %.0d))

julia> x = [1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> Printf.format(fmt, x...)
"1 2 3"

```

---

<div class="post-metadata">

### Author: ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)
#### Post date: [May 23, 2023, 8:56am UTC](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/10 "2023-05-23T08:56:07Z")

</div>

Hi @fatteneder,

Thanks a lot for introducing me to the concept of “splatting”. I’m not sure I fully grasp the solution you proposed, but after reading about this and experimenting I found out that the following works well for me (so far):

```julia
fmt3 = Printf.Format("%8s " * "%14d "^8 * "\n")

for cam = 1:misr_specs.ncameras
    Printf.format(out_stream, fmt3, misr_specs.camera_names[cam], stats[cam, 1:8]...)
end

```

So, if I understand this correctly, adding those three dots after a vector (or array) transforms that vector (or array) into a list of individual elements, though it appears to work only inside a function call.

Thanks again for your input.
