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

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

问题描述

在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()从当前位置生成一个...回溯.... bt是一个指针数组,其中每个指针都是当前调用堆栈中一帧的地址.
  • Profile.lookup(bt[3])返回具有函数名称(以及有关每帧的其他几个详细信息)的LineInfo对象.请注意,bt[1]bt[2]都在backtrace-generation函数本身中,因此我们需要进一步向上移动才能获取调用方.
  • Profile.lookup(...).func返回函数名称(符号:foo)
  • eval(current_module(), Profile.lookup(...))返回与current_module()中的名称:foo关联的功能对象.如果我们修改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.defsMethodTable返回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中没有局部函数"评估的概念,因此,即使有一个变量名,我也认为实际上不可能访问该变量(并且编译器可能会完全忽略未使用或以其他方式使用的局部变量,将其放入寄存器等).

    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自省-获取传递给函数的变量的名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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