关于Base. show的用法疑问,以及julia的执行原理


#1

请问类似Base. show这类函数是普通函数还是构造函数?这类函数是怎么工作的?
比如你定义一个复合类型:struct A{T}
a::T
b::T
end
Base. show(io::IO, z::A) =println(io, z.a,"<>",z.b)
A(1,2)
1<>2
就是说你在对A实例化的时候,Base. show函数作用到了A上?关键是Base. show 函数看起来像一个普通函数,可是并没有显式调用。它是怎么作用到A上的?

类似的函数如index


#2

在REPL里执行,默认会自动显式调show打印结果,后面加;就不打印了。


#3

我想知道具体是怎么样的一个执行过程。
有没有一个函数可以看见具体的执行路线?
类似的
doc 里面的一个类似例子。
struct A <: AbstractArray{Int,1}
a::Int
end
Base. size(s::A) = (s.a,)
Base. getindex(T::A, i::Int) = i*i
A(4)
4_element A:
2
4
6
8
实例化A时,julia是怎么调用的size 和getindex?
好难理解,没有显式调用函数,却调用了,内部是怎么操作的?


#4

Base. show 是 REPL 执行语句时默认调用的,具体的执行位置见代码,

想看调用栈可以这样,调用函数时在合适的地方调用 stacktrace() 显示调用栈。

julia> struct A{T}
       a::T
       b::T
       end

julia> Base. show(io::IO, z::A) = begin println(io, z.a,"<>",z.b); stacktrace() |> display end

julia> A(1,1)
1<>1
21-element Array{Base.StackTraces.StackFrame,1}:
 show at REPL[15]:1 [inlined]                                                                                           
 show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::A{Int64}) at sysimg.jl:194               
 display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at REPL.jl:131                                        
 display(::REPL.REPLDisplay, ::Any) at REPL.jl:135                                                                      
 display(::Any) at multimedia.jl:287                                                                                    
 #invokelatest#1 at essentials.jl:697 [inlined]                                                                         
 invokelatest at essentials.jl:696 [inlined]                                                                            
 print_response(::IO, ::Any, ::Any, ::Bool, ::Bool, ::Any) at REPL.jl:154                                               
 print_response(::REPL.AbstractREPL, ::Any, ::Any, ::Bool, ::Bool) at REPL.jl:139                                       
 (::getfield(REPL, Symbol("#do_respond#40")){Bool,getfield(REPL, Symbol("##50#59")){REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at REPL.jl:713
 #invokelatest#1 at essentials.jl:697 [inlined]                                                                         
 invokelatest at essentials.jl:696 [inlined]                                                                            
 run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at LineEdit.jl:2273
 run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at REPL.jl:1034                                               
 run_repl(::REPL.AbstractREPL, ::Any) at REPL.jl:191                                                                    
 (::getfield(Base, Symbol("##720#722")){Bool,Bool,Bool,Bool})(::Module) at client.jl:355                                
 #invokelatest#1 at essentials.jl:697 [inlined]                                                                         
 invokelatest at essentials.jl:696 [inlined]                                                                            
 run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) at client.jl:339                                                 
 exec_options(::Base.JLOptions) at client.jl:277                                                                        
 _start() at client.jl:425 

run_interface 后一个 inlined 的函数就是我上面给出的连接中的 respond


#5

你试试直接把代码写入一个文件foo.jl里, 然后命令行执行julia foo.jl会不会发生调用?

REPL是一个交互式工具,它会自动帮你调用一些函数,感兴趣可以看看源码https://github.com/JuliaLang/julia/tree/master/stdlib/REPL/src