You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何定义带参数的MULTIPLE-OF类型说明符及同类多参数类型?

Common Lisp动态参数类型说明符的合规实现方案

先明确问题:Paul Graham《ANSI Common Lisp》第234页的multiple-of示例违反了ANSI规范——CLHS规定SATISFIES子句只能接受符号,不能直接使用lambda表达式,执行(typep 12 '(multiple-of 4))会触发类型错误。下面给出两种场景的合规实现方式:

一、正确实现(multiple-of n)类型说明符

核心思路是把原本的lambda闭包绑定到一个唯一命名的函数符号上,让SATISFIES可以合法引用。这里提供两种实现方式:

1. 基础动态生成版

每次定义类型时生成唯一的函数符号,绑定对应的检查逻辑:

(deftype multiple-of (n)
  (let ((predicate-sym (gensym (format nil "MULTIPLE-OF-~A-P-" n))))
    (setf (fdefinition predicate-sym)
          (lambda (x) (zerop (mod x n))))
    `(and integer (satisfies ,predicate-sym))))

这种方式简单直接,但相同n值会重复生成不同的函数符号,适合临时使用。

2. 缓存优化版

用哈希表缓存相同参数对应的谓词函数,避免重复生成:

(defvar *multiple-of-pred-cache* (make-hash-table))

(deftype multiple-of (n)
  (let ((predicate-sym (or (gethash n *multiple-of-pred-cache*)
                           (let ((new-sym (gensym (format nil "MULTIPLE-OF-~A-P-" n))))
                             (setf (fdefinition new-sym)
                                   (lambda (x) (zerop (mod x n)))
                                   (gethash n *multiple-of-pred-cache*) new-sym)
                             new-sym))))
    `(and integer (satisfies ,predicate-sym))))

多次调用(multiple-of 4)会复用同一个函数符号,更高效。

二、实现多参数类型说明符(类似(integer * *))

以实现(between low high)类型(检查数值在[low, high]区间内)为例,同样采用缓存+动态函数的思路:

(defvar *between-pred-cache* (make-hash-table :test #'equal))

(deftype between (low high)
  (let ((cache-key (cons low high))
        predicate-sym)
    (setf predicate-sym (or (gethash cache-key *between-pred-cache*)
                            (let ((new-sym (gensym (format nil "BETWEEN-~A-~A-P-" low high))))
                              (setf (fdefinition new-sym)
                                    (lambda (x) (and (>= x low) (<= x high)))
                                    (gethash cache-key *between-pred-cache*) new-sym)
                              new-sym)))
    `(and number (satisfies ,predicate-sym))))

调用示例:

(typep 7 '(between 3 10)) ; 返回T
(typep 15 '(between 3 10)) ; 返回NIL

内容的提问来源于stack exchange,提问作者Jérôme Radix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:05:27