Julia 似乎没有使用字符串来执行插值 [英] Julia does not appear to be using string to perform interpolation
问题描述
官方文档说明:
连接和字符串插值都调用string()
将对象转换成字符串形式
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))
在 REPL 中,倒数第二行计算结果为 hello MyType(4)
,而最后一行计算结果(如预期)为 hello world
.
The second last line evaluates to hello MyType(4)
at the REPL, while the last line evaluates (as expected) to hello world
.
那我做错了什么?
(我仍在使用 v0.4,但官方文档版本表明应该没有任何区别.)
(I am still on v0.4 but the official doc versions indicate that shouldn't make any difference.)
推荐答案
文档完全正确:
julia> expand(:(println("hello $m")))
:(println((Base.string)("hello ",m)))
也就是说,println("hello $m")
等价 到 println(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.
但是,你的超载
Base.string(m::MyType) = "world"
不是重载 string
的正确方法.此方法仅涵盖类型为 MyType
的单个参数的情况.(这就是为什么,顺便说一句,您的代码似乎适用于连接:该特定示例涉及在单个参数上调用 string
.如果您编写了 "$m,结果将是相同的"
.) 重载它的正确方法是
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")
起初可能看起来很奇怪.这必须重载的原因是因为 string
委托给 print
而委托给 show
.
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))
结果符合预期.
作为脚注,请注意您的示例可以更高效地编写为
As a footnote, note that your example can be more performantly written as
println("hello ", m)
这避免了中间字符串的创建.这说明了 为什么 系统设置为 string
调用 print
调用 show
:IO 方法更多通用并且可以直接打印到各种形式的 IO,而如果反过来,则必须在发送到 IO 之前将内容转换为字符串(需要临时分配,因此性能较差).
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.
这篇关于Julia 似乎没有使用字符串来执行插值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!