调试Scala中的功能代码

Adr*_*ian 31 debugging functional-programming scala

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

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

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

Ada*_*ung 34

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

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

这将打印出来:

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

它偶尔会帮助我.

  • @missingfaktor:官方说来,它是K组合子的一个变种.Raymond Smullyan有一本名为*To Mock A Mockingbird*的非常着名的数学书,它解释了使用鸟类的组合逻辑,本书确实使用红隼代表K组合,这个术语甚至已经超越了本书.简而言之:是的. (7认同)
  • 用println回到洞穴调试?天啊. (6认同)
  • +1。这就是所谓的红est组合器,对吗? (2认同)
  • 这里的问题之一是Java的.class文件的调试元数据格式根本无法以小于一行的粒度记录调试元数据。对于这样的功能代码(即使在Java(!)中也是如此),您将需要一种在(子)表达级别表达调试元数据的方法。因此,基本上,您会陷入使用`tap`调试`printf`,重新格式化为多行以及(暂时)将子表达式分解为`val`的情况。 (2认同)

Apo*_*isp 11

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

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

  • 不确定我理解你的观点.不是"表达式的渐进评价"与"检查中间函数返回值"相同吗? (4认同)
  • 是的,不是不同意你,只是指出传统的IDE调试工具完全没用. (2认同)