2017-10-11 1 views
0

에 한 번만 기능과 캐시 값을 실행 나는 그것을 실행되지 않은 경우, 나는 그것이 몇 가지 방법을 실행하고 그 결과를 반환하려면,이하여 runonce 함수를 호출 그래서스칼라

def runOnce(request: Request): Future[Result] = { 
} 

같은 기능을 가지고 . 실행 된 경우 원래 결과를 반환하기를 원합니다 (들어오는 요청은 동일합니다). 내가 그렇게

첫 번째 경우에 수행하는 방법에
lazy val hydratedModel = hydrateImpl(request) 

future for efficient filtering 
def fetchHydratedModel(): Future[HydratedModelRequest] = { 
    hydratedModel 
} 

같은 더 PARAM가없는 경우

나는 그것을 할 수 있습니까?

+0

를 호출 할 것인가? 당신이 원하는 것에 대한 기술은 메모 화 (memoization)라고 불리지 만 요청에 적용하는 것은 나에게 매우 이상하게 보입니다. memoization에 대해서는 [스칼라에서 암기 할 수있는 일반적인 방법이 있습니까?] (https://stackoverflow.com/questions/16257378/is-there-a-generic-way-to-memoize-in-scala) – Suma

+0

기능이 필요합니까? 자사의 이름과 전화 가치 평가 전략으로 전화를 더 할 수 있습니다. – Pavel

답변

0

이 사용자의 설정에 따라 할 가능성이 더 나은 방법이 있지만 간단한 해결책이 request 실제로 각 호출에 대해 동일한 경우

private var model: Option[Future[HydratedModelRequest]] = None 

def runOnce(request: Request): Future[Request] = { 
    if (model.isEmpty) { 
    model = hydrateImpl(request) 
    } 

    model.get 
} 

을 다음을 수행하는 것입니다, 다른 옵션이 필요로하는 것 요청은 암묵적으로 이루어지며 느리게 수화됩니다.

implicit val request: Request 
lazy val hydratedRequest: Future[HydratedModelRequest] = hydrateImpl(request) 
1

기능 메모이 제이션이다이 문제에 대한 일반적인 해결책이있다; 순수 함수 (부작용이없는 함수 - 비 순수 함수에서는 작동하지 않음)에 대해 함수 호출의 결과는 동일한 인수 값 세트에 대해 항상 동일해야합니다. 따라서 최적화는 첫 번째 호출에서 값을 캐시하고 후속 호출에서이를 반환하는 것입니다.

다음과 같은 (하나의 인자를 가진 순수 기능을위한 메모이 제이션 클래스) 같은 것을 함께이를 달성 할 수

/** Memoize a pure function `f(A): R` 
* 
* @constructor Create a new memoized function. 
* @tparam A Type of argument passed to function. 
* @tparam R Type of result received from function. 
* @param f Pure function to be memoized. 
*/ 
final class Memoize1[A, R](f: A => R) extends (A => R) { 

    // Cached function call results. 
    private val result = scala.collection.mutable.Map.empty[A, R] 

    /** Call memoized function. 
    * 
    * If the function has not been called with the specified argument value, then the 
    * function is called and the result cached; otherwise the previously cached 
    * result is returned. 
    * 
    * @param a Argument value to be passed to `f`. 
    * @return Result of `f(a)`. 
    */ 
    def apply(a: A) = result.getOrElseUpdate(a, f(a)) 
} 

/** Memoization companion */ 
object Memoize1 { 

    /** Memoize a specific function. 
    * 
    * @tparam A Type of argument passed to function. 
    * @tparam R Type of result received from function. 
    * @param f Pure function to be memoized. 
    */ 
    def apply[A, R](f: A => R) = new Memoize1(f) 
} 

당신이 memoizing있는 기능이 hydrateImpl이라고 가정하면, 다음을 정의 할 수 있습니다 다음과 같이 runOnce을 사용 (이되고 있습니다 val 아닌 def) :

함수가 정말 지금까지 한 번에 하나의`request`보다 더
val runOnce = Memoize1(hydrateImpl) 
runOnce(someRequest) // Executed on first call with new someRequest value, cached result subsequently.