反射与内省
Julia 提供了各种运行时反射功能。
模块绑定
可以使用 names(m::Module)
获取 Module
的导出名称,它将返回一个包含表示导出绑定的 Symbol
元素的数组。names(m::Module, all = true)
返回 m
中所有绑定的符号,无论其导出状态如何。
数据类型字段
可以使用 fieldnames
查询 DataType
字段的名称。例如,给定以下类型,fieldnames(Point)
返回一个包含表示字段名称的 Symbol
的元组
julia> struct Point
x::Int
y
end
julia> fieldnames(Point)
(:x, :y)
Point
对象中每个字段的类型存储在 Point
变量本身的 types
字段中
julia> Point.types
svec(Int64, Any)
虽然 x
被注释为 Int
,但 y
在类型定义中未加注释,因此 y
默认为 Any
类型。
类型本身表示为称为 DataType
的结构。
julia> typeof(Point)
DataType
请注意,fieldnames(DataType)
给出了 DataType
本身每个字段的名称,其中一个字段是上面示例中观察到的 types
字段。
子类型
可以使用 subtypes
列出任何 DataType
的直接子类型。例如,抽象 DataType
AbstractFloat
有四个(具体)子类型
julia> subtypes(AbstractFloat)
4-element Vector{Any}:
BigFloat
Float16
Float32
Float64
任何抽象子类型也将包含在此列表中,但其进一步的子类型将不会包含;可以递归应用 subtypes
来检查完整的类型树。
数据类型布局
DataType
的内部表示在与 C 代码交互时至关重要,并且可以使用多个函数来检查这些细节。 isbitstype(T::DataType)
如果 T
以与 C 兼容的对齐方式存储,则返回 true。 fieldoffset(T::DataType, i::Integer)
返回相对于类型开头的字段i的(字节)偏移量。
函数方法
可以使用 methods
列出任何泛型函数的方法。可以使用 methodswith
在方法分派表中搜索接受给定类型的方法。
展开和降低
如 元编程 部分所述,macroexpand
函数提供了给定宏的未引用和插值表达式 (Expr
) 形式。要使用 macroexpand
,请对表达式块本身进行 quote
(否则,将对宏进行求值,并将结果传递给它!)。例如
julia> macroexpand(@__MODULE__, :(@edit println("")) )
:(InteractiveUtils.edit(println, (Base.typesof)("")))
Base.Meta.show_sexpr
和 dump
函数用于显示任何表达式的 S-expr 样式视图和深度嵌套详细信息视图。
最后,Meta.lower
函数提供了任何表达式的“降低”形式,对于理解语言结构如何映射到诸如赋值、分支和调用之类的基本操作特别有用
julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] ))
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = 1 + 2
│ %2 = sin(0.5)
│ %3 = Base.vect(%1, %2)
└── return %3
))))
中间和编译表示
检查函数的降低形式需要选择要显示的特定方法,因为泛型函数可能具有许多具有不同类型签名的函数。为此,可以使用 code_lowered
进行特定于方法的代码降低,并使用 code_typed
获取类型推断形式。 code_warntype
会在 code_typed
的输出中添加突出显示。
更接近机器层面,可以使用 code_llvm
打印函数的 LLVM 中间表示,最后可以使用 code_native
获取编译后的机器码(这将触发任何以前未被调用的函数的 JIT 编译/代码生成)。
为了方便起见,上述函数有宏版本,它们会自动获取标准函数调用并展开参数类型
julia> @code_llvm +(1,1)
; @ int.jl:87 within `+`
; Function Attrs: sspstrong uwtable
define i64 @"julia_+_476"(i64 signext %0, i64 signext %1) #0 {
top:
%2 = add i64 %1, %0
ret i64 %2
}
有关更多信息,请参阅 @code_lowered
、@code_typed
、@code_warntype
、@code_llvm
和 @code_native
。
调试信息的打印
上述函数和宏都使用关键字参数 debuginfo
来控制打印的调试信息级别。
julia> @code_typed debuginfo=:source +(1,1)
CodeInfo(
@ int.jl:53 within `+'
1 ─ %1 = Base.add_int(x, y)::Int64
└── return %1
) => Int64
debuginfo
的可能值为::none
、:source
和 :default
。默认情况下不会打印调试信息,但这可以通过设置 Base.IRShow.default_debuginfo[] = :source
来更改。