Is show() the correct way to return a String representation of a struct?

Viewed 226

In C# and Java, we have the toString() method to return a String representation of an object.

The closest I've seen in Julia is show(), but I'm not entirely sure if it's the correct function.

struct Person
   name::String
   age::Int32
end

amber = Person("Amber",22) 
println(amber) # Output: Person("Amber", 22)

If I want a little more control over the return String, I can do:

function Base.show(io::IO, person::Person)
    return "Name: $(person.name) Age: $(person.age)"
end

println(show(amber)) # Output: Name: Amber Age: 22

Do I have to call show() directly everytime? Can I pass it to println() and have it call show()? In C# and Java, if toString() is overridden, Console.writeLine() or System.out.println() will call toString(), no need to call it directly.

4 Answers

This works the same in Julia:

julia> struct Person
          name::String
             age::Int32
       end

julia>

julia> amber = Person("Amber",22)
Person("Amber", 22)

julia> Base.show(io::IO, person::Person) = println("Name: $(person.name) Age: $(person.age)")

julia> amber
Name: Amber Age: 22

This question is close to a duplicate of:

How to overload Base.show for custom array types?

Once you define a show(::IO, ::Person) method:

julia> Base.show(io::IO, person::Person) = print(io, "The name is $(person.name), and they are $(person.age) years old")

You can use the repr function to get that output as a String:

julia> repr(amber)
"The name is Amber, and they are 22 years old"

You can also use the string function

julia> string(amber)
"The name is Amber, and they are 22 years old"

which by default falls back to show and so returns the same result. However, you can customize that by defining a print(::IO, ::Person) method:

julia> Base.print(io::IO, person::Person) = print(io, "name: $(person.name)\nage: $(person.age)")

julia> string(amber)
"name: Amber\nage: 22"

julia> repr(amber)
"The name is Amber, and they are 22 years old"

Note that this doesn't change the repr output: repr depends directly on show, whereas string depends on print.

In practice, you can use this to, for eg., have string(amber) return a plain list of information about the struct that could be useful for debugging, by defining print to print that information. And meanwhile, repr(amber) can return a human readable interpretation of the struct useful to the end user of the type, by defining show to show such an interpretation.

In addition to the answer above, if you want a String, we can always write our own to_string() function in addition to show():

function toString(person::Person)
  return "Name $(person.name) Age: $(person.age)"
end

amber = Person("Amber",22) 
println(toString(amber)) # Output: Name Amber Age: 22

I wonder if you want to replicate toString() behavior if you can just define a Base.string() method

struct Person
   name::String
   age::Int32
end

Base.string(person::Person) = "Name: $(person.name) Age: $(person.age)"

p = Person("Julia", 5)

string(p)
"Name: Julia Age: 5"
Related