2016-10-16 14 views
5

官方的文檔狀態:朱莉婭似乎沒有使用字符串來執行插值

兩個級聯和串插呼叫string()將對象轉換爲字符串形式

但是,下面的最低工作示例似乎證明不是:

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

第二行最後評估爲hello MyType(4)在REPL,而最後一行評估(如預期)到hello world

那麼我做錯了什麼?

(我仍然在V0.4但官方文檔版本表明,不應有任何區別。)

回答

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)) 

後,如預期的結果。


作爲一個註腳,請注意您的例子可以更performantly寫成

println("hello ", m) 

避免了中間串的創建。這說明了爲什麼系統設置爲使得string調用print,它調用show:IO方法更通用,可以直接打印到各種形式的IO,而如果以相反方式進行打印,則必須將事物轉換爲字符串(需要臨時分配,因此性能較差),然後再發送給IO。

+1

很好的答案!真的很好解釋。一個簡單的問題:之前我被這個問題困住了(我重載了'Base。<'而不是重載'Base'。isless'),所以我想知道是否有任何提示知道哪些函數超載?是否有資源顯示哪些功能位於「鏈條底部」? –

+0

ps如果答案很長,我可以使這個單獨的StackOverflow問題。讓我知道,我會這樣做... –

+0

說實話,我不知道答案。我不知道這樣的資源。儘管如此,這將很好。 –