尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

scope-capture之brk断点完全指南:loose/loose-with/loose-with-err三件套如何暂停并操控执行流

scope-capture之brk断点完全指南:loose/loose-with/loose-with-err三件套如何暂停并操控执行流 scope-capture之brk断点完全指南loose/loose-with/loose-with-err三件套如何暂停并操控执行流【免费下载链接】scope-captureProject your Clojure(Script) REPL into the same context as your code when it ran项目地址: https://gitcode.com/gh_mirrors/sc/scope-capturescope-capture是一个专为 Clojure(Script) 打造的REPL 调试工具库它的sc.api/brk宏能让运行中的代码像打断点一样瞬间暂停再用loose、loose-with、loose-with-err三件套从 REPL 里自由操控后续执行流——继续运行、偷换返回值或直接抛异常中断程序。本指南带你从零掌握这套REPL 断点玩法。为什么需要 brk让代码停下来听你指挥传统调试靠看堆栈、打日志而 scope-capture 倡导的方法是把代码运行时的局部环境scope原样搬进 REPL让你在真实的上下文中反复实验快速定位问题。sc.api/spy是只看不拦记录表达式所在作用域的局部变量并照常执行而sc.api/brk更进一步——它会阻塞当前线程把程序冻在断点处直到你在 REPL 中主动放行。这正是调试器断点的核心体验却无需依赖任何 IDE。 两个关键 ID 帮你定位冻住的时刻Code Site代码位置负数 ID如-2在编译期生成标记你放brk的位置Execution Point执行点正数 ID如3每次经过断点都会新增一个。源码中brk的定义见src/sc/api.cljc其中明确列出了三种恢复执行的方式。一键设置 brk 断点两步走第 1 步在你的代码里用(sc.api/brk ...)包住想检查的表达式(defn greet! [first-name] (let [msg (str Hello, (str/capitalize first-name) !)] (println (sc.api/brk msg)))) ;; 断点打在这里编译后 REPL 会打印一条日志告诉你在 Code Site-2处将保存哪些局部变量first-name、msgBRK -2 .../tutorial.clj:183 At Code Site -2, will save scope with locals [first-name msg]第 2 步在另一个线程里调用该函数关键原因见后文避坑章节(def fut (future (greet! jude))) ;; BRK [3 -2] ... saved scope with locals [first-name msg], ;; use sc.api/loose(-...) to resume execution.此时程序被挂起fut的状态停在:pending而 REPL 依然可以随意操作。你甚至可以用sc.api/defsc 3或sc.api/letsc 3 ...把挂起时的全部局部变量还原出来现场验尸。loose 三件套对比一条命令决定程序接下来怎么走暂停只是手段操控执行流才是精髓。scope-capture 提供三个函数对应三种放行策略实现见src/sc/api.cljc中loose、loose-with、loose-with-err三个定义函数行为典型用途sc.api/loose正常评估被包裹的表达式继续执行纯粹想路过看一眼变量sc.api/loose-with用你提供的值替换表达式结果不执行原表达式偷换参数验证下游反应sc.api/loose-with-err直接抛出你指定的异常中断执行阻止下游副作用、跳出循环对照greet!的例子三种放行方式各显神通;; ① 正常放行 → 照常打印 Hello, Jude! (sc.api/loose 3) ;; ② 偷换返回值 → 打印你指定的文案 (sc.api/loose-with 3 Bonjour, Jude !) ;; ③ 抛出异常 → 阻止 println 继续跑下去 (sc.api/loose-with-err 3 (ex-info Aaaaaarrrrgh {}))三个函数都支持省略 ep-id 的便捷写法(sc.api/loose)会自动作用于最近一次挂起的执行点适合手速流。实战技巧三件套的高频使用场景场景一条件性断点只抓特定调用。在循环里放brk会每轮都卡住。想只暂停某几轮放行后立即禁用该代码位置(sc.api/loose 3) ;; 先放行 (sc.api/disable! -2) ;; 之后不再触发暂停disable!/enable!一对兄弟函数可以随时开关某个 Code Site 的暂停行为且幂等安全。场景二用异常剪断危险路径。当你只想观察前半段、又不想让数据库写入等副作用发生时loose-with-err是首选——它模拟此处炸雷让程序带着你指定的异常信息提前退出配合try/catch观察回滚逻辑非常方便。场景三A/B 实验。loose-with让你在不改一行代码的情况下把某个中间值换成任意试验值看下游如何消化。这是假数据验证法在 REPL 里的天然实现。避坑指南新手最容易踩的 3 个坑⚠️坑 1在 REPL 线程里直接执行含brk的表达式。断点一旦触发它挂起的正是你敲命令的线程——你自己把自己锁死了。务必用future、独立线程或让程序自己调用到断点。brk的文档注释里专门强调you should never execute a(brk ...)block directly from your REPL thread。⚠️坑 2断点代码混进生产环境。spy/brk会持续保存运行时数据长期运行会造成内存泄漏。调试完毕记得移除宏调用或至少用sc.api/dispose! ep-id释放单个执行点占用的内存。⚠️坑 3挂起的执行点忘了处理就dispose!。对一个正处于暂停状态的执行点调用dispose!会以抛出异常的方式强制恢复其执行——这有时是特性有时是意外使用前想清楚。另外大对象刷屏时用安静版宏sc.api/brkqt只打印值的类型不打印完整内容见src/sc/api.cljc中的定义。ClojureScript 用户请注意在 JVM 编译的 ClojureScript 环境中defsc/letsc无法自动关联 Code Site需要把两个 ID 一起写在向量里例如(sc.api/defsc [3 -2])。brk三件套本身不受影响照常使用。快速上手5 分钟安装与验证若你还没装 scope-capture以 Leiningen 为例在~/.lein/profiles.clj的:userprofile 中加入依赖与自动注入建议只装在本地环境不放进项目依赖:dependencies [[vvvvalvalval/scope-capture 0.3.3]] :injections [(require sc.api)]需要获取项目源码时可执行git clone https://gitcode.com/gh_mirrors/sc/scope-capture克隆后推荐先跑一遍lab/sc/lab/tutorial.clj完整的 haversine 找 bug 教程和doc/Tutorial.md把spy→defsc→brk→loose的完整链路亲手走一遍断点调试的手感立刻就有了。总结三句话记住 brk 三件套loose—— 放行让代码自己跑完loose-with—— 拦截用你的值顶替表达式的结果loose-with-err—— 掀桌直接抛异常终止下游。配合defsc/letsc还原现场、disable!开关断点、dispose!清理内存scope-capture 让你仅凭一个 REPL 就拥有了断点、单步、条件断点级别的调试能力——而且是纯 Clojure、跨平台、零 IDE 依赖的。【免费下载链接】scope-captureProject your Clojure(Script) REPL into the same context as your code when it ran项目地址: https://gitcode.com/gh_mirrors/sc/scope-capture创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表