Julia Learner
Julia Learner

Reputation: 3032

The @printf macro produces errors with a predefined format string

When running Julia 1.0.0 the @printf macro seems to not be able to accept either a constant format string or a variable format string. This is shown below.

julia> using Printf

julia> const fmt = "%10d %6.4f"
"%10d %6.4f"

julia> @printf(fmt, 101, 65.4039)
ERROR: LoadError: ArgumentError: @printf: first or second argument must be a format string

julia> fmt2 = "%10d %6.4f"
"%10d %6.4f"

julia> @printf(fmt2, 101, 65.4039)
ERROR: LoadError: ArgumentError: @printf: first or second argument must be a format string

I found a discussion for an early version of Julia (2013) where this kind of thing was not allowed.

I see in the 1.0.0 documentation for @printf the following syntax:

@printf([io::IOStream], "%Fmt", args...)

Does this imply that "@Fmt" must be hardcoded into the @printf parameters when called?

Has anything changed with regard to using a dynamic format string since 2013 with regard to Julia's @printf?

Upvotes: 2

Views: 1453

Answers (2)

Samuel Liew
Samuel Liew

Reputation: 79113

Moved answer from an edit to the question, by Julia Learner:


Get a dynamic format string using the Formatting package

It appears that the use of @printf has not changed up to version 1.0.0.

For anyone else wanting a dynamic format string capability, here is what I have found for Julia 1.0.0 and the 9/20/2018 version of the Formatting package. From its documentation

This package is pure Julia. Setting up this package is like setting up other Julia packages:

Pkg.add("Formatting")

You will probably get an error error using 1.0.0:

julia>  Pkg.add("Formatting")
ERROR: UndefVarError: Pkg not defined

*Solution: Access the new package manager in Julia 1.0.0 with the ] key, see docs.

Note: The following command is case sensitive, add formatting will fail.

(v1.0) pkg> add Formatting

Now your first test of printfmt may fail as shown:

julia> printfmt("Testing")
ERROR: UndefVarError: STDOUT not defined

Solution: Add a standard out parameter and spell stdout in lowercase:

julia> printfmt(stdout, "Testing")
Testing

Now we have a working dynamic format capability in Julia 1.0.0:

Next you may get the following error:

julia> const fmt = "%10d %6.4"
ERROR: cannot assign variable Formatting.fmt from module Main

Solution: Use a format variable name that does not conflict with the Formatting package. Also note the use, in this example, of a Python-style format string:

julia> frmt = "{:10d} {:6.4f}"  # Python-style format string
"{:10d} {:6.4f}"

julia> printfmt(stdout, frmt, 10, 65.4039)
        10 65.4039

Upvotes: 0

carstenbauer
carstenbauer

Reputation: 10147

As far as I can see by inspecting the implementation of @printf this is currently not supported. Note that it checks for args[1] isa AbstractString which isn't true in your example (where typeof(args[1]) == Symbol).

If you feel this should be added, you could file a feature request here.

UPDATE:

Actually I should have read the github issue that you linked. Although it still isn't supported the way you want it, there are nice ways to handle cases like this. As has been suggested by Stefan here you can do:

julia> using Printf

julia> const fmt = "%10d %6.4f"
"%10d %6.4f"

julia> @eval myprintf(x,y) = @printf($fmt,x,y)
myprintf (generic function with 1 method)

julia> myprintf(101, 65.4039)
       101 65.4039

This defines a (efficient) function myprintf which has the format string build in.

Upvotes: 3

Related Questions