加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala:memoize一个函数,无论函数需要多少参数?

发布时间:2020-12-16 09:29:51 所属栏目:安全 来源:网络整理
导读:我想在Scala中写一个memoize函数,无论函数对象是什么,都可以应用于任何函数对象。我想这样做,让我使用单一的memoize实现。我对语法很灵活,但理想情况下,memoize出现在非常接近功能声明的地方,而不是后面的函数。我也想避免首先声明原来的功能,然后是
我想在Scala中写一个memoize函数,无论函数对象是什么,都可以应用于任何函数对象。我想这样做,让我使用单一的memoize实现。我对语法很灵活,但理想情况下,memoize出现在非常接近功能声明的地方,而不是后面的函数。我也想避免首先声明原来的功能,然后是第二个声明为记忆版本。

所以一些理想的语法可能是这样的:

def slowFunction(<some args left intentionally vague>) = memoize {
  // the original implementation of slow function
}

甚至这是可以接受的:

def slowFUnction = memoize { <some args left intentionally vague> => {
  // the original implementation of slow function
}}

我已经看到了这样做的方式,每个arity功能必须重新定义memoize,但是我想避免这种方法。原因是我需要实现类似于memoize的功能(即其他装饰器),并且要求每个arity功能都要复制每个功能太多了。

一个方法做回忆,这需要你重复memoize声明(所以不好)是在In Scala 2.8,what type to use to store an in-memory mutable data table?。

解决方法

您可以使用类型类方法来处理可靠性问题。您仍然需要处理您想要支持的每个功能,但不是为了每个arity / decorator组合:

/**
 * A type class that can tuple and untuple function types.
 * @param [U] an untupled function type
 * @param [T] a tupled function type
 */
sealed class Tupler[U,T](val tupled: U => T,val untupled: T => U)

object Tupler {
   implicit def function0[R]: Tupler[() => R,Unit => R] =
      new Tupler((f: () => R) => (_: Unit) => f(),(f: Unit => R) => () => f(()))
   implicit def function1[T,R]: Tupler[T => R,T => R] = 
      new Tupler(identity,identity)
   implicit def function2[T1,T2,R]: Tupler[(T1,T2) => R,((T1,T2)) => R] = 
      new Tupler(_.tupled,Function.untupled[T1,R]) 
   // ... more tuplers
}

然后可以按如下方式实现装饰器:

/**
 * A memoized unary function.
 *
 * @param f A unary function to memoize
 * @param [T] the argument type
 * @param [R] the return type
 */
class Memoize1[-T,+R](f: T => R) extends (T => R) {
   // memoization implementation
}

object Memoize {
   /**
    * Memoize a function.
    *
    * @param f the function to memoize
    */
   def memoize[T,R,F](f: F)(implicit e: Tupler[F,T => R]): F = 
      e.untupled(new Memoize1(e.tupled(f)))
}

您的“理想”语法将不起作用,因为编译器会假定传入memoize的块是一个0参数的词法闭包。但是,您可以使用以下语法:

// edit: this was originally (and incorrectly) a def
lazy val slowFn = memoize { (n: Int) => 
   // compute the prime decomposition of n
}

编辑:

为了消除大量用于定义新装饰器的样板,您可以创建一个特征:

trait FunctionDecorator {
   final def apply[T,T => R]): F = 
      e.untupled(decorate(e.tupled(f)))

   protected def decorate[T,R](f: T => R): T => R
}

这允许您重新定义Memoize装饰器

object Memoize extends FunctionDecorator {
   /**
    * Memoize a function.
    *
    * @param f the function to memoize
    */
   protected def decorate[T,R](f: T => R) = new Memoize1(f)
}

不要在Memoize对象上调用memoize方法,而是直接应用Memoize对象:

// edit: this was originally (and incorrectly) a def
lazy val slowFn = Memoize(primeDecomposition _)

要么

lazy val slowFn = Memoize { (n: Int) =>
   // compute the prime decomposition of n
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读