Julia does not appear to be using string to perfor

2019-06-22 11:37发布

The official docs state:

Both concatenation and string interpolation call string() to convert objects into string form

However, the following minimum working example seems to demonstrate otherwise:

type MyType
    x::Int
end
import Base.string
Base.string(m::MyType) = "world"
m = MyType(4)
println("hello $m")
println("hello " * string(m))

The second last line evaluates to hello MyType(4) at the REPL, while the last line evaluates (as expected) to hello world.

So what am I doing wrong?

(I am still on v0.4 but the official doc versions indicate that shouldn't make any difference.)

1条回答
疯言疯语
2楼-- · 2019-06-22 12:17

The documentation is perfectly correct:

julia> expand(:(println("hello $m")))
:(println((Base.string)("hello ",m)))

That is to say, println("hello $m") is equivalent to println(string("hello", m)). By the time the code is compiled or interpreted, they are the same thing.

However, your overload

Base.string(m::MyType) = "world"

is not the correct way to overload string. This method only covers the case with a single argument of type MyType. (This is why, incidentally, your code seemed to work for concatenation: that particular example involved calling string on a single argument. The results would have been the same if you had written "$m".) The correct way to overload it is

Base.show(io::IO, m::MyType) = print(io, "world")

which may seem weird at first. The reason this must be overloaded is because string delegates to print which delegates to show.

After updating your minimum working example to

type MyType
    x::Int
end
Base.show(io::IO, m::MyType) = print(io, "world")
m = MyType(4)
println("hello $m")
println("hello " * string(m))

the result is as expected.


As a footnote, note that your example can be more performantly written as

println("hello ", m)

which avoids the creation of intermediate strings. This illustrates why the system is set up so that string calls print which calls show: the IO method is more generic and can print to various forms of IO directly, whereas if it went the other way around, one would have to convert things into strings (requiring temporary allocation and thus poor performance) before sending to IO.

查看更多
登录 后发表回答