官方文件声明:
串联和字符串插值调用
string()
将对象转换为字符串形式
但是,以下最低工作示例似乎表明了其他情况:
type MyType
x::Int
end
import Base.string
Base.string(m::MyType) = "world"
m = MyType(4)
println("hello $m")
println("hello " * string(m))
第二行最后一行在REPL处评估为hello MyType(4)
,而最后一行评估(按预期)为hello world
。
那么我做错了什么?
(我仍然在v0.4,但官方文档版本表明不应该有任何区别。)
答案 0 :(得分:9)
文档完全正确:
julia> expand(:(println("hello $m")))
:(println((Base.string)("hello ",m)))
也就是说,println("hello $m")
等效到println(string("hello", m))
。在编译或解释代码时,它们是相同的。
然而,你的超载
Base.string(m::MyType) = "world"
不是重载string
的正确方法。此方法仅涵盖具有MyType
类型的单个参数的情况。 (这就是为什么顺便说一下,你的代码似乎适用于连接:这个特定的例子涉及在一个参数上调用string
。如果你写了"$m"
,结果就会一样。)正确重载的方法是
Base.show(io::IO, m::MyType) = print(io, "world")
起初可能看起来很奇怪。这必须重载的原因是因为string
委托print
代理show
。
将您的最低工作示例更新为
type MyType
x::Int
end
Base.show(io::IO, m::MyType) = print(io, "world")
m = MyType(4)
println("hello $m")
println("hello " * string(m))
结果与预期一致。
作为脚注,请注意您的示例可以更加高效地编写为
println("hello ", m)
避免创建中间字符串。这说明为什么系统已设置,以便string
调用print
调用show
:IO方法更通用,可以打印到各种形式的IO直接,如果它反过来,在发送到IO之前,必须将事物转换为字符串(需要临时分配,因此性能不佳)。