【发布时间】:2018-03-22 14:34:05
【问题描述】:
在 emacs lisp 中,是否有一些无样板的方法来检查类型条件,例如带有明确错误消息的“数字列表”?
cl-check-type 宏对于验证参数的类型非常有用,可防止在无效输入在子函数的子函数中某处产生类型错误时出现模糊的错误消息。
但是,我找不到一种在不添加大量样板代码的情况下以产生清晰错误消息的方式验证即使是中等复杂类型的好方法。
一个明确的错误消息应该包含参数的名称,并说明参数期望实现的内容,通常是参数的值(尽管这对于可能是大树的参数实际上可能是个坏主意)。
示例
假设一个函数(mysum NUMLIST) 需要一个数字列表作为参数。如果wrong-type-argument 发出信号,则错误信号最好包含参数的变量名称,并解释预期的内容。
在这个简单的例子中,可以通过三种方式违反条件:
- NUMLIST 可能不是列表(cons 或 nil)。
-
NUMLIST 可能不是正确的列表,例如
(1 2 . 3)。 - NUMLIST 项可能不是数字。
理想情况下,所有这些都将被
之类的东西覆盖;; Pseudocode, doesn't actually work
(cl-check-type numlist (listof numberp))
据我所知,cl-check-type 宏没有变体允许说“每个都满足类型谓词的项目列表”,因此不能直接使用它。通常我会写一些类似的东西
(cl-check-type numlist list)
(dolist (item list)
(cl-check-type item numberp))
但这会产生较差的错误消息:
- 对于 NUMLIST 是
(1 2 . 3),错误消息和堆栈跟踪都不容易清楚地表明问题是由numlist引起的。 - 对于 numlist 为
(1 b 3),错误消息将引用内部变量item,而不是指示该项目来自哪个函数参数。
我能想到的最好的是
(condition-case nil
(dolist (item numlist)
(cl-check-type item numberp))
(wrong-type-argument
(signal 'wrong-type-argument
(list '(listof numberp) numlist 'numlist))))
使用伪谓词(listof ...) 的缺点是缺乏明确定义的含义。
虽然可以定义谓词mypackage-list-of-numbers-p,但结果错误
(wrong-type-argument mypackage-list-of-numbers-p SOME-VALUE-IN-VIOLATION numlist)
不会像能够使用预定义的谓词那样不言自明;如果listof 是一个有效的类型谓词,则假定看到错误消息的程序员知道(listof numberp) 的确切含义,而mypackage-list-of-numbers-p 可能隐藏任何数量的意外(例如,要求数字是整数),并且定义 mypackage-list-of-numbers-p 仍将构成样板代码。
带有‘define-widget’的递归类型
对于更复杂的结构,尤其是像任意深度树这样的递归结构,问题会变得更糟。此时可以通过定义(并检查)使用define-widget 定义的自定义类型来减少样板文件,这也允许递归。
然而,对于像“数字列表”这样的简单案例,无论是就代码行数而言,还是就使用该函数的程序员需要查找的文档量而言,这似乎都是大材小用。
【问题讨论】:
标签: tree elisp typechecking