Reflection and introspection

    The exported names for a are available using , which will return an array of Symbol elements representing the exported bindings. names(m::Module, all = true) returns symbols for all bindings in m, regardless of export status.

    DataType fields

    The names of DataType fields may be interrogated using . For example, given the following type, fieldnames(Point) returns a tuple of Symbols representing the field names:

    The type of each field in a Point object is stored in the types field of the Point variable itself:

    1. julia> Point.types

    While x is annotated as an Int, y was unannotated in the type definition, therefore y defaults to the Any type.

    Types are themselves represented as a structure called DataType:

    The direct subtypes of any DataType may be listed using . For example, the abstract DataType AbstractFloat has four (concrete) subtypes:

    1. julia> subtypes(AbstractFloat)
    2. 4-element Vector{Any}:
    3. BigFloat
    4. Float16
    5. Float32
    6. Float64

    Any abstract subtype will also be included in this list, but further subtypes thereof will not; recursive application of may be used to inspect the full type tree.

    The internal representation of a DataType is critically important when interfacing with C code and several functions are available to inspect these details. isbits(T::DataType) returns true if T is stored with C-compatible alignment. returns the (byte) offset for field i relative to the start of the type.

    The methods of any generic function may be listed using methods. The method dispatch table may be searched for methods accepting a given type using .

    As discussed in the Metaprogramming section, the function gives the unquoted and interpolated expression (Expr) form for a given macro. To use macroexpand, quote the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example:

    Finally, the function gives the lowered form of any expression and is of particular interest for understanding how language constructs map to primitive operations such as assignments, branches, and calls:

    1. julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] ))
    2. @ none within `top-level scope'
    3. │ %2 = sin(0.5)
    4. │ %3 = Base.vect(%1, %2)
    5. └── return %3
    6. ))))

    Inspecting the lowered form for functions requires selection of the specific method to display, because generic functions may have many methods with different type signatures. For this purpose, method-specific code-lowering is available using code_lowered, and the type-inferred form is available using . code_warntype adds highlighting to the output of .

    Closer to the machine, the LLVM intermediate representation of a function may be printed using by code_llvm, and finally the compiled machine code is available using (this will trigger JIT compilation/code generation for any function which has not previously been called).

    For convenience, there are macro versions of the above functions which take standard function calls and expand argument types automatically:

    For more informations see @code_lowered, , @code_warntype, , and @code_native.

    1. julia> @code_typed debuginfo=:source +(1,1)
    2. CodeInfo(
    3. @ int.jl:53 within `+'
    4. 1 ─ %1 = Base.add_int(x, y)::Int64
    5. └── return %1

    Possible values for debuginfo are: :none, :source, and. Per default debug information is not printed, but that can be changed by setting Base.IRShow.default_debuginfo[] = :source.