gpt4 book ai didi

scala - 如何在 Scala 中跟踪函数评估?

转载 作者:行者123 更新时间:2023-12-01 05:14:44 25 4
gpt4 key购买 nike

我正在学习 Scala 中的函数式编程,并且经常需要跟踪函数评估以更好地了解它是如何工作的。

例如,具有以下功能:

def foldRight[A,B](l: List[A], z: B)(f: (A, B) => B): B =
l match {
case Nil => z
case Cons(x, xs) => f(x, foldRight(xs, z)(f))
}

对于以下调用:
foldRight(Cons(1, Cons(2, Cons(3, Nil))), 0)(_ + _)

我想打印它的评估跟踪,如下所示:
foldRight(Cons(1, Cons(2, Cons(3, Nil))), 0)(_ + _)
1 + foldRight(Cons(2, Cons(3, Nil)), 0)(_ + _)
1 + (2 + foldRight(Cons(3, Nil), 0)(_ + _))
1 + (2 + (3 + (foldRight(Nil, 0)(_ + _))))
1 + (2 + (3 + (0)))
6

目前我正在手动或注入(inject)丑陋的打印品。我怎样才能以一种方便优雅的方式实现这一目标?

最佳答案

我假设 Cons 和::是相同的操作。
如果您不介意只获取当前元素和累加器,则可以执行以下操作:

def printable(x:Int, y:Int): Int = {
println("Curr: "+x.toString+" Acc:"+ y.toString)
x+y
}
foldRight(List(1, 2, 3, 4), 0)(printable(_,_))
//> Curr: 4 Acc:0
//| Curr: 3 Acc:4
//| Curr: 2 Acc:7
//| Curr: 1 Acc:9
//| res0: Int = 10

如果您想要整个“堆栈跟踪”,这将为您提供您询问的输出,尽管它远非优雅:
def foldRight[A, B](l: List[A], z: B)(f: (A, B) => B): B = {
var acc = if (l.isEmpty) "" else l.head.toString
def newAcc(acc: String, x: A) = acc + " + (" + x
def rightSide(xs: List[A], z: B, size: Int) = xs.toString + "," + z + ")" * (l.size - size + 1)
def printDebug(left: String, right: String) = println(left + " + foldRight(" + right)

def go(la: List[A], z: B)(f: (A, B) => B): B = la match {
case Nil => z
case x :: xs => {
acc = newAcc(acc, x)
printDebug(acc, rightSide(xs, z, la.size))
f(x, go(xs, z)(f))
}
}
if (l.isEmpty) z
else f(l.head, go(l.tail, z)(f))
}

注意:要摆脱变量“acc”,您可以在“go”函数中创建第二个累加器

这也返回您要求的输出,但不会掩盖 foldRight。
class Trace[A](z: A) {
var list = List[A]()
def store(x: A) = {
list = list :+ x
}

def getTrace(level: Int): String = {
val left = list.take(level).map(x => s"$x + (").mkString
val right = list.drop(level).map(x => s"$x,").mkString
if (right.isEmpty)
s"${left.dropRight(4)}" + ")" * (list.size - 1)
else
s"${left}foldRight(List(${right.init}), $z)" + ")" * (list.size - level - 1)
}

def getFullTrace: String =
{ for (i <- 0 to list.size) yield getTrace(i) }.mkString("\n")

def foldRight(l: List[A], z: A)(f: (A, A) => A): A = l match {
case Nil => z
case x :: xs => store(x); f(x, foldRight(xs, z)(f))
}
}

val start = 0
val t = new Trace[Int](start)
t.foldRight(List(1, 2, 3, 4), start)(_ + _)
t.getFullTrace

关于scala - 如何在 Scala 中跟踪函数评估?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21766805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com