繁体   English   中英

调试Scala中的功能代码

[英]Debugging functional code in Scala

调试功能代码肯定比调试命令式代码更棘手。 请参阅此处此处此处的讨论。 “功能”调试应该支持检查函数/闭包/ monad的返回值。 是否有任何调试器/ IDE具有(计划拥有)检查中间返回值的能力?

例如,要在Scala中调试此行,我应该能够逐步执行4次函数调用,并在返回r之前检查每一步的返回r

val r=(ls filter (_>1) sort (_<_) zipWithIndex) filter {v=>(v._2)%2==0} map{_._1}

我认为每个人建议将这个东西分解为更易于管理的块是最好的方法。 用于调试较小的表情一招是窃取Ruby的龙头作用,如所描述这里 “tap”允许你将表达式粘贴在这样的链中间,并且可能会打印出一些调试值,如下所示:

val ls = List(1,2,3).map(_ * 2)
                .tap(soFar => println("So far: " + soFar))
                .map(_ * 2)
println(ls)

这将打印出来:

到目前为止:列表(2,4,6)
清单(4,8,12)

它偶尔会帮助我。

在纯粹的功能设置中,单步执行并不像您想象的那么有用。 由于一切都由纯函数组成,您可以使用消除过程单独测试这些部分。 在惰性评估设置中,单步执行代码甚至不太有用。

例如,在Haskell中调试程序,你根本不会对跟踪函数调用感兴趣。 您感兴趣的是一系列中间函数返回值。 在任何函数式语言中,能够为任何表达式提供这样的跟踪将是一个非常有用的功能。

我知道简洁是非常好的,我同意你的看法,IDE应该有助于在这些情况下进行调试。 但是暂时我改变了我的编码风格以协助调试。 以我个人的风格,我会将你的例子实现为:

val noZeroLs = ls.filter(_>1)
val sortedLs = noZeroLs.sort(_<_)
val indexedNoZeroLs = sortedLs.zipWithIndex
val everySecondIndexedL = indexedNoZeroLs.filter(v => (v._2) % 2 == 0)
val everySecondL = everySecondIndexedL.map(_._1)

提出有意义的名字是困难/费力的,但它确实帮助你识别愚蠢的错误; 可以帮助其他人了解正在发生的事情; 并且肯定有助于调试。

我解决这个问题的方法是将表达式分解为将结果绑定到REPL中的val的部分。 当我满意的时候,我甚至可以编写一个测试用例,它和我在REPL中做的一样,这样我就可以确保事情保持原样,以便我或其他人可以稍后回来查看更明确的版本。

使用repl进行探索的能力加上漂亮且易于使用的测试工具包使得调试器几乎已经过时了。

当然是YMMV。

当您尝试调试自己的代码时很有用,但在调试scala lang或其他库时,您无法更改代码:(

如果您没有IDE,您仍然可以使用我写的这个工具:

https://github.com/JohnReedLOL/scala-trace-debug

要打印中间值,您可以采用以下示例:

val result=(lists.filter(_>1).sort(_<_).zipWithIndex).filter{v=>(v._2)%2==0}.map{_._1}

并添加痕迹:

import scala.trace.implicitlyTraceable
val result=(lists.filter(_>1).out.sort(_<_).println.zipWithIndex).filter{v=>(v._2)%2==0}.out.map{_._1}.out

隐式转换允许您打印。

启动Scala 2.13 ,如Adam Rabung的回答中所提到的链接操作tap已经包含在标准库中,并且可以通过打印管道的中间版本来用于调试:

import scala.util.chaining._

scala> val ls = List(1,2,3).map(_ * 2).tap(println).map(_ * 2).tap(println)
List(2, 4, 6)
List(4, 8, 12)
ls: List[Int] = List(4, 8, 12)

tap链操作在返回原始值时对值(在本例中为List )应用副作用(在本例中为println ):

def tap [U](f:(A)=> U):A

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM