Is there a built in macro like @show that returns a string?

I want the macro @show but to return a string instead of printing. Does something like that already exist?

Not that I know of, but it would be pretty easy to write this by copying the @show definition. e.g.

macro showstring(exs...)
    args = []
    for ex in exs
        push!(args, sprint(Base.show_unquoted, ex), " = ", esc(ex), '\n')
    end
    return :(string($(args...)))
end

Why do you need such a macro? Seems a little odd to me.

You might be interested in the repr function. It doesn’t have the pretty x = ... part but that’s easy to do manually and not a difficult macro otherwise.

julia> "x = " * repr(rand(1:10,2,3))
"x = [9 6 3; 8 4 5]"
2 Likes

Thanks. Well, among other things, I thought it might be handy when using @assert. The second argument in @assert isn’t very flexible: it’s just a string, but I’d really like it to automatically show everything in the expression. I didn’t want to replace @assert because in the docs it says: “An assert might be disabled at various optimization levels.” which is a good thing. I suppose I could implement my own mechanism to deactivate my @assert replacement. Actually, that might be ideal.

But, I regularly find myself a bit frustrated with functions that print instead of returning a string… So, maybe what I need is a macro that converts a function that takes an IO as first arg to return a string.

You don’t need a macro for this. That’s exactly what the sprint function does. Or, at a lower level, you can print to an IOBuffer and then take! that to a string — this is how sprint is implemented.

1 Like

Thanks! I thought I had just run across something that does that but I couldn’t find it again.

I’m not the OP and this thread is old, but I’ve come here because I want to replace @show . . . with @info . . . maxlog=1:

function call_me_many_times()
   # . . . 
   @show array1, array2
end

@show is more convenient because it shows the names of the variables and its contents in a more compact way than @info but the above use of @show can be annoying when the function is called many times while you just want to check the working of your function once. On the other hand, @info has a nice flag maxlog=1, so I would use your macro like this:

using Logging
function call_me_many_times()
   # . . .
   s = @showstring(array1, array2)
   @info s maxlog=1
end

It’s a bit strange to me that no means is provided to specify which I/O stream that @show will send the string into. (Compare with the family printf, sprintf, and fprintf in C.)

[Before you point out, I’ve read the thread where the OP asks how to execute only once a section of code within a function. The solutions there are to me a bit overkill just to avoid multiple @show’s.]

Doesn’t @info "" array1 array2 work for you? It supports all @info options and prints variable names as well.

2 Likes

Yes and yes. I should’ve highlighted that, in my previous message. Here I quote my words:

[Emphasis is added here.] @info is verbose:

julia> a = [1,2,3,4]

julia> @show a;
a = [1, 2, 3, 4]

julia> using Logging

julia> @info "" a;
┌ Info:
│   a =
│    4-element Vector{Int64}:
│     1
│     2
│     3
â””     4

So, if there is an option to @info to use a @show like compact format, then that would be what I’m looking for. (I suppose that with the Logging package, the destinations of the logs can also be controlled, right?)

That’s just the display of the default ConsoleLogger; you can fully customize logging and set your logger to display the information however you like (with some work), and to send the info wherever you like (to the repl, to a file, over the network, etc). See the JuliaLogging website for an overview: https://julialogging.github.io/

1 Like