Skip to content

A publicly facing reflection API #20555

@oxinabox

Description

@oxinabox
Contributor

Julia allows for reflection.
It is infact really powerful. You can do crazy things like examine the code for a function programatically.

My issue is that it is largely based on unexported methods, and on directly reading various fields. Sometimes in complicated ways. Code based on this "privately" facing API breaks every single release.

Consider, this example that came up in code I am writing.
I would like to find out if a function has any methods that take a keyword arg with a given name.

function methods_with_kwarg(func::Function, kwarg_name::Symbol)
    #BLACK-MAGIC, 0.5 only
    supporting_methods = Method[]
    ml = methods(func)
    if isdefined(ml.mt, :kwsorter)
        kwsort_t = typeof(ml.mt.kwsorter)
        for mmm in ml.ms
            sig = mmm.sig
            all_kwarg_list = Base.kwarg_decl(sig, kwsort_t)
            if kwarg_name  all_kwarg_list
                push!(supporting_methods, mmm)
            end
        end
    end
    supporting_methods
end
julia> methods_with_kwarg(repeat, :outer)

1-element Array{Method,1}:
 - repeat(A::AbstractArray) at abstractarraymath.jl:329

So in that code, 2 Public API method was used: methods and isdefined.
And then 5 private API methods/fields: MethodTable.kwsorter, Method.sig, MethodList.ms, MethodList.mt, and Base.kwarg_decl.

They are all undocumented. and I know they change in 0.6, and in 0.4, and 0.3.
It would be nice to be able to do reflection without having to go deep into the guts of the language.

Towards this end, I feel it is necessary to make a consideration of what reflection methods a language like julia should provide, and then define, export, and document methods to that end.

Activity

Ismael-VC

Ismael-VC commented on Jun 16, 2017

@Ismael-VC
Contributor

We should start with a list of this public and private methods/fuelds. Then change the short cryptic names and document everything even if not exported, so we can suggest how the API should look like. I didnt know about those private methods.

oxinabox

oxinabox commented on Jun 16, 2017

@oxinabox
ContributorAuthor

So that implementation can change, all fields basically require functions,
that retrieve their value.
Eg. paramaters(T) = T.parameters

smldis

smldis commented on Dec 31, 2017

@smldis

I think this needs a (short or advanced) plan for 1.0/1.x at list for the publicly facing part.

smldis

smldis commented on Dec 31, 2017

@smldis

I'll list some reflection uses I found for fields reflection (not listing the most common patterns that involve testing and documenting in repl and in compiled docs).

  • julia (cholmod.jl):
let offset = fieldoffset(C_Sparse{Float64}, findfirst(name -> name === :stype, fieldnames(C_Sparse{Float64})))
  • gadfly (chain method)
for name in fieldnames(Data)
    #more code
    getfield(data, name)
    #more code
  • Cxx.jl:
vals = [llvmconst(getfield(val,i)) for i = 1:length(fieldnames(T))]
oxinabox

oxinabox commented on Jan 13, 2019

@oxinabox
ContributorAuthor

another I want is

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureIndicates new feature / enhancement requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @smldis@Ismael-VC@oxinabox@brenhinkeller

        Issue actions

          A publicly facing reflection API · Issue #20555 · JuliaLang/julia