julia introspection - 获取传递给函数的变量名称 [英] julia introspection - get name of variable passed to function

查看:9
本文介绍了julia introspection - 获取传递给函数的变量名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Julia 中,有什么方法可以获取传递给函数的名称?

In Julia, is there any way to get the name of a passed to a function?

x = 10
function myfunc(a)
# do something here
end
assert(myfunc(x) == "x")

我需要使用宏还是有提供自省的本机方法?

Do I need to use macros or is there a native method that provides introspection?

推荐答案

好吧,自相矛盾:从技术上讲在一个(相当有限的)条件下,这是可能的,在一个(相当有限的)条件下:函数名必须只有一个方法签名.这个想法与 Python 的此类问题的答案非常相似.在演示之前,我必须强调这些是内部编译器细节,可能会发生变化.简要说明:

Ok, contradicting myself: technically this is possible in a very hacky way, under one (fairly limiting) condition: the function name must have only one method signature. The idea is very similar the answers to such questions for Python. Before the demo, I must emphasize that these are internal compiler details and are subject to change. Briefly:

julia> function foo(x)
           bt = backtrace()
           fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
           Base.arg_decl_parts(fobj.env.defs)[2][1][1]
       end
foo (generic function with 1 method)

julia> foo(1)
"x"

让我再次强调 这是一个坏主意,不应该用于任何事情!(好吧,除了回溯显示).这基本上是愚蠢的编译器技巧",但我展示它是因为玩这些对象可能是一种教育,并且解释确实为@ejang 的澄清评论提供了更有用的答案.

Let me re-emphasize that this is a bad idea, and should not be used for anything! (well, except for backtrace display). This is basically "stupid compiler tricks", but I'm showing it because it can be kind of educational to play with these objects, and the explanation does lead to a more useful answer to the clarifying comment by @ejang.

解释:

  • bt = backtrace() 从当前位置生成 ... backtrace ....bt 是一个指针数组,其中每个指针是当前调用堆栈中的一个帧的地址.
  • Profile.lookup(bt[3]) 返回一个 LineInfo 对象,其中包含函数名称(以及每个帧的其他一些详细信息).请注意,bt[1]bt[2] 都在 backtrace-generation 函数本身中,因此我们需要进一步向上堆栈以获取调用者.
  • Profile.lookup(...).func 返回函数名(符号:foo)
  • eval(current_module(), Profile.lookup(...)) 返回与名称:foo关联的函数对象current_module() 中的代码>.如果我们修改function foo的定义返回fobj,那么注意REPL中的foo对象的等价性:

  • bt = backtrace() generates a ... backtrace ... from the current position. bt is an array of pointers, where each pointer is the address of a frame in the current call stack.
  • Profile.lookup(bt[3]) returns a LineInfo object with the function name (and several other details about each frame). Note that bt[1] and bt[2] are in the backtrace-generation function itself, so we need to go further up the stack to get the caller.
  • Profile.lookup(...).func returns the function name (the symbol :foo)
  • eval(current_module(), Profile.lookup(...)) returns the function object associated with the name :foo in the current_module(). If we modify the definition of function foo to return fobj, then note the equivalence to the foo object in the REPL:

julia> function foo(x)
           bt = backtrace()
           fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
       end
foo (generic function with 1 method)

julia> foo(1) == foo
true

  • fobj.env.defs 返回 MethodTable 中的第一个 Method 条目,用于 foo/fobj

  • fobj.env.defs returns the first Method entry from the MethodTable for foo/fobj

    关于函数只有一个方法签名的限制,原因是在MethodTable中会列出多个签名(见defs.next).据我所知,目前没有公开的接口来获取与给定帧地址关联的特定方法.(作为高级读者的练习:这样做的一种方法是修改 jl_getFunctionInfo 中的地址查找功能,以同时返回损坏的函数名称,然后可以将其与特定方法重新关联调用;但是,我认为我们目前没有存储来自损坏名称的反向映射 -> 方法).

    Regarding the restriction that the function have only one method signature, the reason is that multiple signatures will all be listed (see defs.next) in the MethodTable. As far as I know there is no currently exposed interface to get the specific method associated with a given frame address. (as an exercise for the advanced reader: one way to do this would be to modify the address lookup functionality in jl_getFunctionInfo to also return the mangled function name, which could then be re-associated with the specific method invocation; however, I don't think we currently store a reverse mapping from mangled name -> Method).

    还要注意 (1) 回溯很慢 (2) 在 Julia 中没有函数局部" eval 的概念,所以即使有变量名,我相信也无法实际访问变量 (并且编译器可能会完全忽略未使用或其他方式的局部变量,将它们放入寄存器等)

    Note also that (1) backtraces are slow (2) there is no notion of "function-local" eval in Julia, so even if one has the variable name, I believe it would be impossible to actually access the variable (and the compiler may completely elide local variables, unused or otherwise, put them in a register, etc.)

    至于评论中提到的IDE风格的内省使用:如上所示的foo.env.defs是对象内省"的一个起点.在调试方面,Gallium.jl 可以检查给定帧中的 DWARF 局部变量信息.最后,JuliaParser.jl 是 Julia 解析器的纯 Julia 实现,在几个 IDE 用于从高层次内省代码块.

    As for the IDE-style introspection use mentioned in the comments: foo.env.defs as shown above is one place to start for "object introspection". From the debugging side, Gallium.jl can inspect DWARF local variable info in a given frame. Finally, JuliaParser.jl is a pure-Julia implementation of the Julia parser that is actively used in several IDEs to introspect code blocks at a high level.

    这篇关于julia introspection - 获取传递给函数的变量名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆