【问题标题】:Does Julia have function decorators?Julia 有函数装饰器吗?
【发布时间】:2021-04-25 03:43:31
【问题描述】:

在某些语言(如 Python)中,有一些函数装饰器,它们看起来像宏,位于函数定义之上。装饰器为函数本身提供了一些额外的功能。

Julia 是否以任何方式支持这种函数装饰器的想法?是否可以使用宏来实现相同的目标?

【问题讨论】:

  • 在 Python 中,装饰器只不过是把函数作为参数并以某种方式返回修改后的函数的函数。在 Julia 中,我们定义的“函数”不是一个完整的函数,而是可能是多方法的一小部分,这增加了一些复杂性。我很好奇这样的事情是否容易实现。
  • 我没有写很多宏,但我认为宏通常是 Julia 中“装饰”方法的方式。它实际上并没有以同样的方式工作,因为宏在编译过程中发挥作用(编译 Julia 与解释 Python)。您可以通过编写一个接收方法并返回方法的方法来制作更像 Python 的装饰器的东西。请注意有条件地定义内部方法的问题。

标签: julia


【解决方案1】:

这是使用ExprTools.jl 的宏实现此目的的一种方法:

import ExprTools

macro dec(decorator, inner_def)
    inner_def = ExprTools.splitdef(inner_def)
    outer_def = copy(inner_def)
    fname = get(inner_def, :name, nothing)
    if fname !== nothing
        @assert fname isa Symbol
        inner_def[:name] = Symbol(fname, :_inner)
    end
    outer_def[:body] = Expr(:call,
        :($decorator($(ExprTools.combinedef(inner_def)))),
        get(outer_def, :args, [])...,
        get(outer_def, :kwargs, [])...,
    )
    return esc(ExprTools.combinedef(outer_def))
end
julia> _time(f) = (x...) -> (t0=time(); val=f(x...); println("took ", time()-t0, " s"); val)
_time (generic function with 1 method)

julia> @dec _time function foo(x, y)
           return x + y
       end
foo (generic function with 1 method)

julia> foo(1, 2)
took 9.5367431640625e-7 s
3

但是,至少根据我的经验,这在惯用的 Julia 程序中很少出现。我首先会考虑您的具体问题是否可以通过使用简单的高阶函数和特征的多次调度来更好地解决,这通常有助于更好的可组合性。

【讨论】:

    【解决方案2】:

    为了扩展@SilvioMayolo 的评论,Julia 具有非常优雅的宏功能,比 Python 装饰器更通用。 事实上,Julia 的宏将任何 表达式 作为输入,并且该宏可以挂钩抽象语法树以返回修改后的表达式。

    您要查找的关键字是“元编程”。

    Here你可以找到官方文档和here一个方便的教程。

    【讨论】:

      猜你喜欢
      • 2021-03-07
      • 2020-05-20
      • 2014-07-21
      • 1970-01-01
      • 2021-04-19
      • 2010-10-27
      • 2011-10-04
      • 1970-01-01
      • 2019-02-23
      相关资源
      最近更新 更多