2024 Clojure现状调查中分享您的想法!

欢迎!请参阅关于页面以了解更多关于如何工作的信息。

0
REPL

问题陈述

Clojure的REPL能够参数化其功能几乎各个方面,包括未捕获异常的打印方式。在当前实现中,这些自定义钩子作为参数传递并通过闭包执行,意味着一旦REPL开始运行,它们不能被更改。

许多开发工具想要覆盖REPL如何处理未捕获的错误。有用的自定义示例包括(但不限于)

  • 格式化的异常信息(包括空格和ANSI颜色)
  • 某些类型异常的替代表示(例如,Spec错误)
  • 进入图形交互模式以更好地检查ex-data。

目前,这种类型的自定义必须在REPL启动之前应用,这意味着更改REPL显示错误需要来自(或Leiningen之类的第三方工具的)插件的支持。

替代方案

<BR/>
1. 不采取任何行动

需要第三方工具来创建REPL中的自定义异常处理。这些工具有不同的技术来完成这项工作

  • nREPL可以拦截线上的异常并通过中间件传递
  • Leiningen插件更改了{{clojure.main/repl-caught}}的根绑定。
  • Boot允许用户构建一个任务来调用{{clojure.main/repl}}并带有所需的参数。

用户将继续根据自己的工具偏好选择其中之一。

优点
1. 不会对现有代码造成任何影响或更改。

权衡
1. 工具将继续实施各自不同的、有时是黑客般的技术来打印自定义异常。
2. 旨在提供替代异常处理的任何库都将绑定到特定的启动工具。

  1. 使REPL异常处理器动态重新绑定

如果REPL异常处理器是一个动态的线程局部变量,用户和库可以改变当前运行的REPL的行为。

优点
1. 用户和库可以自由覆盖异常的打印方式,不管Clojure是如何启动的。
2. 完全向后兼容现有工具。

权衡
1. 库的作者可以提供“不良”或推理不充分的错误打印机。这仍然可以通过启动工具实现,但由于库的屏障更低,所以更加容易。

附带的补丁实现了此选项。

  1. 鼓励用户启动新的REPL

在许多Clojure环境中,可以从另一个REPL中显式启动REPL。此子REPL可以具有所需的:caught钩子。

优点
1. 不会对现有代码造成任何影响或更改。
2. “函数式纯”,并且与当前REPL的明显设计相一致。

权衡
1. 在Clojure开发者中,存在一个非平凡的子集,他们并不确切知道REPL是如何工作的。这很可能会让他们感到困惑,或者增加认知负荷。鉴于这部分初学者/中级开发者正是最初预期通过增强错误消息来帮助的对象,这个解决方案是适得其反的。
2. 无论好坏,许多现有的和广泛使用的工作工具都不支持这一点。例如,在nREPL中完全不起作用。然而,即使是功能最简单的命令行REPL的表现也会变差;发送EOF(无论是意外还是其他原因)总会杀死次级REPL,而没有任何反馈说明发生了什么。

2 个答案

0

评论人:alexmiller

在 * } var 上,最好说明处理程序签名,即它接受异常,预计将打印或以其他方式处理异常,并且它的返回值将被忽略。

除了REPL中的更改,您是否可以考虑添加 dynamic-repl-caught 并将其更改为REPL中的默认捕获处理程序?或者甚至直接更改 repl-caught。

0
参考资料:https://clojure.atlassian.net/browse/CLJ-2040(由lvanderhart报告)
...