热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么REPL没有显示函数调用的完整跟踪?

我正在尝试通过《Common Lisp:符号计算的温和介绍》一书来学习 Common Lisp 。此外,我正在使用 SBCL、Emacs 和 Slime。在第7章的进阶部分,作者建议使用trace功能

我正在尝试通过《Common Lisp:符号计算的温和介绍》一书来学习 Common Lisp 。此外,我正在使用 SBCL、Emacs 和 Slime。

在第7章的进阶部分,作者建议使用trace功能。这无疑是一个非常有价值的工具。我很高兴看到它起作用了。

然而,显然,我的工具并不能完全像作者介绍的那样工作。

做如下定义后:

(defun find-first-odd (x)
(find-if #’oddp x))

(defun find-first-odd (x)
(find-if #’oddp x))

并在 REPL 上运行:

> (dtrace find-first-odd oddp)

他得到:

> (find-first-odd ’(2 4 6 7 8))
----Enter FIND-FIRST-ODD
| X = (2 4 6 7 8)
| ----Enter ODDP
| | NUMBER = 2
| --ODDP returned NIL
| ----Enter ODDP
| | NUMBER = 4
| --ODDP returned NIL
| ----Enter ODDP
| | NUMBER = 6
| --ODDP returned NIL
| ----Enter ODDP
| | NUMBER = 7
| --ODDP returned T
--FIND-FIRST-ODD returned 7
7

在我的环境中,使用相同的定义:

并进行跟踪(通过健全性检查):

CL-USER> (trace)
NIL
CL-USER> (trace find-first-odd oddp)
(FIND-FIRST-ODD ODDP)

我得到:

CL-USER> (find-first-odd '(2 4 6 7 8))
0: (FIND-FIRST-ODD (2 4 6 7 8))
0: FIND-FIRST-ODD returned 7

这看起来很尴尬,因为(trace)评估表明包含了奇数谓词。但是,在函数调用之后,它不会显示为跟踪操作。

在另一个示例中,我的两个函数都是由我定义的,并且不oddp涉及谓词等原语,它完美地工作:

(defun half (n) (* n 0.5))
(defun average (x y)
(+ (half x) (half y)))
CL-USER> (trace half average)
(HALF AVERAGE)
CL-USER> (average 3 7)
0: (AVERAGE 3 7)
1: (HALF 3)
1: HALF returned 1.5
1: (HALF 7)
1: HALF returned 3.5
0: AVERAGE returned 5.0
5.0

有没有办法解决这个问题?

回答

您可以调用trace多个函数,并且需要调用trace要查看其跟踪信息的每个函数。所以,你可以这样做:

CL-USER> (trace find-first-odd oddp)
(FIND-FIRST-ODD ODDP)
CL-USER> (find-first-odd '(2 4 6 7 8))
0: (FIND-FIRST-ODD (2 4 6 7 8))
0: FIND-FIRST-ODD returned 7
7

但是,内置函数可能不会产生任何跟踪信息,并且oddp在 SBCL 中看起来是不可跟踪的。这可能是因为oddp在 SBCL 中内联了。您可以尝试使用notinline声明:

(defun find-first-odd (x)
(declare (notinline oddp))
(find-if #'oddp x))

CL-USER> (trace find-first-odd oddp)
(FIND-FIRST-ODD ODDP)
CL-USER> (find-first-odd '(2 4 6 7 8))
0: (FIND-FIRST-ODD (2 4 6 7 8))
1: (ODDP 2)
1: ODDP returned NIL
1: (ODDP 4)
1: ODDP returned NIL
1: (ODDP 6)
1: ODDP returned NIL
1: (ODDP 7)
1: ODDP returned T
0: FIND-FIRST-ODD returned 7
7

如果失败,您可以将内置函数包装在另一个可以跟踪的函数定义中:

(defun my-oddp (&rest args)
(apply #'oddp args))
(defun find-first-odd-trace (x)
(find-if #'my-oddp x))

CL-USER> (untrace)
T
CL-USER> (trace find-first-odd-trace my-oddp)
(FIND-FIRST-ODD-TRACE MY-ODDP)
CL-USER> (find-first-odd-trace '(2 4 6 7 8))
0: (FIND-FIRST-ODD-TRACE (2 4 6 7 8))
1: (MY-ODDP 2)
1: MY-ODDP returned NIL
1: (MY-ODDP 4)
1: MY-ODDP returned NIL
1: (MY-ODDP 6)
1: MY-ODDP returned NIL
1: (MY-ODDP 7)
1: MY-ODDP returned T
0: FIND-FIRST-ODD-TRACE returned 7
7

您可能还想查看对 的调用find-if。在这里你可以看到,虽然find-if是一个内置函数,但在 SBCL 中它是可追溯的:

CL-USER> (trace find-if)
(FIND-IF)
CL-USER> (find-first-odd-trace '(2 4 6 7 8))
0: (FIND-FIRST-ODD-TRACE (2 4 6 7 8))
1: (FIND-IF # (2 4 6 7 8))
2: (MY-ODDP 2)
2: MY-ODDP returned NIL
2: (MY-ODDP 4)
2: MY-ODDP returned NIL
2: (MY-ODDP 6)
2: MY-ODDP returned NIL
2: (MY-ODDP 7)
2: MY-ODDP returned T
1: FIND-IF returned 7
0: FIND-FIRST-ODD-TRACE returned 7
7






推荐阅读
  • Egg.js 中间件详解与应用实例
    Egg.js 的中间件机制与 Koa 类似,均采用洋葱模型。每当开发一个中间件时,就像是在洋葱外增加了一层。本文将通过一个简单的中间件示例,详细介绍 Egg.js 中间件的编写方法及其应用场景,帮助读者更好地理解和使用这一功能。 ... [详细]
  • 本文详细解析了JSONP(JSON with Padding)的跨域机制及其工作原理。JSONP是一种通过动态创建``标签来实现跨域请求的技术,其核心在于利用了浏览器对``标签的宽松同源策略。文章不仅介绍了JSONP的产生背景,还深入探讨了其具体实现过程,包括如何构造请求、服务器端如何响应以及客户端如何处理返回的数据。此外,还分析了JSONP的优势和局限性,帮助读者全面理解这一技术在现代Web开发中的应用。 ... [详细]
  • 使用 Python 中的 Matplotlib Axes 获取标签方法详解 ... [详细]
  • PHP中元素的计量单位是什么? ... [详细]
  • 智能网联汽车自动驾驶功能测试场地的方法与标准要求
    智能网联汽车自动驾驶功能测试场地的方法与标准要求 ... [详细]
  • Understanding the Distinction Between decodeURIComponent and Its Encoding Counterpart
    本文探讨了 JavaScript 中 `decodeURIComponent` 和其编码对应函数之间的区别。通过详细分析这两个函数的功能和应用场景,帮助开发者更好地理解和使用它们,避免常见的编码和解码错误。 ... [详细]
  • 池子比率:BSV 区块链上的去中心化金融应用——Uniswap 分析
    池子比率:BSV 区块链上的去中心化金融应用——Uniswap 分析 ... [详细]
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • 基于Node.js的高性能实时消息推送系统通过集成Socket.IO和Express框架,实现了高效的高并发消息转发功能。该系统能够支持大量用户同时在线,并确保消息的实时性和可靠性,适用于需要即时通信的应用场景。 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 本文详细解析了如何使用 jQuery 实现一个在浏览器地址栏运行的射击游戏。通过源代码分析,展示了关键的 JavaScript 技术和实现方法,并提供了在线演示链接供读者参考。此外,还介绍了如何在 Visual Studio Code 中进行开发和调试,为开发者提供了实用的技巧和建议。 ... [详细]
  • 期末Web开发综合实践项目:运用前端技术打造趣味小游戏体验
    期末Web开发综合实践项目中,学生通过运用HTML、CSS和JavaScript等前端技术,设计并实现了一款趣味性十足的小游戏。该项目不仅检验了学生对前端基础知识的掌握情况,还提升了他们的实际操作能力和创意设计水平。视频链接展示了项目的最终成果,直观呈现了游戏的互动性和视觉效果。 ... [详细]
  • 微信支付授权目录配置详解及操作步骤
    在使用微信支付时,若通过WeixinJSBridge.invoke方法调用支付功能,可能会遇到“当前页面URL未注册”的错误提示,导致get_brand_wcpay_request:fail调用微信JSAPI支付失败。为解决这一问题,需要正确配置微信支付授权目录,确保支付页面的URL已成功注册。本文将详细介绍微信支付授权目录的配置步骤和注意事项,帮助开发者顺利完成支付功能的集成与调试。 ... [详细]
  • 本文介绍了如何通过掌握 IScroll 技巧来实现流畅的上拉加载和下拉刷新功能。首先,需要按正确的顺序引入相关文件:1. Zepto;2. iScroll.js;3. scroll-probe.js。此外,还提供了完整的代码示例,可在 GitHub 仓库中查看。通过这些步骤,开发者可以轻松实现高效、流畅的滚动效果,提升用户体验。 ... [详细]
  • 在Java中,匿名函数作为一种无名的函数结构,无法独立调用;而在JavaScript中,不仅有类似的匿名函数,还有立即执行函数(IIFE)和闭包等高级特性。立即执行函数同样基于匿名函数实现,但会在定义时立即执行,而闭包则通过嵌套函数来捕获外部变量,实现数据封装和持久化。这些不同的函数形式在实际开发中各有应用场景,理解其特点有助于更好地利用语言特性进行编程。 ... [详细]
author-avatar
凰千寻_847
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有