Julia似乎没有使用字符串来执行插值

Col*_*ers 5 string string-interpolation julia

官方文件说:

连接和字符串插值调用string()将对象转换为字符串形式

但是,以下最低工作示例似乎证明了其他情况:

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

第二行最后一行评估为hello MyType(4)REPL,而最后一行评估(按预期)为hello world.

那么我做错了什么?

(我仍然在v0.4,但官方文档版本表明不应该有任何区别.)

Fen*_*ang 9

文档完全正确:

julia> expand(:(println("hello $m")))
:(println((Base.string)("hello ",m)))
Run Code Online (Sandbox Code Playgroud)

也就是说,println("hello $m")相当于println(string("hello", m)).在编译或解释代码时,它们是相同的.

但是,你的超载

Base.string(m::MyType) = "world"
Run Code Online (Sandbox Code Playgroud)

不是正确的重载方式string.此方法仅涵盖具有单个参数类型的情况MyType.(这就是为什么,顺便说一下,你的代码似乎适用于连接:这个特定的例子涉及调用string一个参数.如果你已经写过,结果将是相同的"$m".)重载它的正确方法是

Base.show(io::IO, m::MyType) = print(io, "world")
Run Code Online (Sandbox Code Playgroud)

一开始可能看起来很奇怪.必须重载的原因是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))
Run Code Online (Sandbox Code Playgroud)

结果如预期.


作为脚注,请注意您的示例可以更加高效地编写为

println("hello ", m)
Run Code Online (Sandbox Code Playgroud)

这避免了中间字符串的创建.这说明了为什么设置系统以便string调用print调用show:IO方法更通用并且可以直接打印到各种形式的IO,而如果它反过来,则必须将事物转换为字符串(需要临时)在发送给IO之前,分配并因此表现不佳.

  • 关于`<`vs`lessless`,最好超载`isless`.用于发现这个的资源是REPL上的`@edit 1> 3`,它获取代码并显示回退到`isless`. (3认同)