Andriy Polishchuk (isorecursive) wrote,
Andriy Polishchuk
isorecursive

Scala: Call-by-Need

Во время дискуссии пришла идея, как на имплицит-конверсиях реализовать call-by-need:
class ~>[A](delayed: => A) {
  private lazy val value = delayed  
  def force() = value
}

implicit def thunkable[A](computation: => A)  =
  new ~>(computation)

implicit def forceable[A](computation: ~>[A]) =
  computation.force

def lazyInR(x: Int, y: ~>[Int]) = {
  val a = x + 5 * y
  val b = y - 5 * x
  a * b
}

def x: Int = {
  println("I'm printed once!");
  2
}

lazyInR(1, x)

http://www.scalakata.com/509aafece4b093f3524f3a1b

Идея состоит в том, чтобы, подобно встроенному функционалу для by-name, требовать для call-by-need вычислений пометки в сигнатуре типа стрелочкой, только не =>, а ~>, которую мы реализуем классом. Это даёт возможность написать имплицит-конверсии из передаваемого по факту в функцию A в ~>[A] (для задержки), и обратно (для форсирования). В первой конверсии и в конструкторе класса A будет задерживаться by-name благодаря =>. Вторая конверсия - из ~>[A] в A, и она состоит просто в вызове метода force, который содержит логику мемоизированного by-name.

Updated:
Более интересный пример с call-by-need списками: http://www.scalakata.com/509ab47ce4b093f3524f3a24
Tags: call-by-need, implicits, lazy, scala
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 3 comments