如何在Scala中跟踪函数评估?
发布时间:2020-12-16 08:43:36 所属栏目:安全 来源:网络整理
导读:我正在学习 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)) } 对于以下电话:
我正在学习
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,0)(_ + _) 1 + foldRight(Cons(2,Nil)),0)(_ + _) 1 + (2 + foldRight(Cons(3,Nil),0)(_ + _)) 1 + (2 + (3 + (foldRight(Nil,0)(_ + _)))) 1 + (2 + (3 + (0))) 6 目前我手动或注射丑陋的印刷品.我怎样才能以方便优雅的方式实现这一目标? 解决方法
我假设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) => 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],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,z)(f)) } } val start = 0 val t = new Trace[Int](start) t.foldRight(List(1,start)(_ + _) t.getFullTrace (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |