微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Scala中的Python样式装饰器

Python中,我可以执行以下操作:

def wrap(f):
    def wrapper(*args, **kwargs):
        print "args: ", args, kwargs
        res = f(*args, **kwargs)
        print "result: ", res
        return res
    return wrapper

这使我可以包装任何函数,而不必考虑它们采用的参数.例如:

In [8]: def f(thing):
    print "in f:", thing
    return 3

In [9]: wrapped_f = wrap(f)

In [10]: wrapped_f(2)
args:  (2,) {}
in f: 2
result:  3
Out[10]: 3

有没有一种方法可以在Scala中做类似的事情(编写一个可以应用于任何函数的包装器,而不管其输入/输出类型如何)?

解决方法:

您当然可以使用宏来执行此操作.您可以使用部分应用程序将方法调用转换为函数

object Foo {
  def bar(i: Int): Int = i + 1
}

val fn = Foo.bar _

defined object Foo
fn: Int => Int = <function1>

现在,您有了一个对象,在这种情况下,其类型为Function1 [Int,Int],您可以将其传递给Scala宏,该对象将如下所示(未经测试):

object DecoratorMacros {

  import reflect.macros.blackBox
  import language.experimental.macros

  def decorate[A <: Function](fn: A): [A] = macro decorate_impl[A]

  def decorate_impl[A: c.WeakTypeTag](c: blackBox.Context) = {
    import c.universe._
    val type = weakTypeOf[A]
    ...
  }
}

在宏的主体中,您可以检查fn:A的整个类型签名,其中将包括参数.然后,您可以编写代码来实现所需的副作用,并返回一个可以调用函数.像这样:

DecoratorMacros.decorate(Foo.bar _)(42)

宏相当复杂,但是如果您认为这是您想走的路,我可以详细说明.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐