Common lisp 序列第一个元素上的公共Lisp分派
是否可以定义对序列中的特定元素(例如第一个)进行调度的方法?不使用“完全通用”的谓词调度机制是否可以做到这一点 下面我有一个程序,它以负范式重写命题演算中的一个表达式(即所有的否定出现在变量之前)。它还删除了除Common lisp 序列第一个元素上的公共Lisp分派,common-lisp,Common Lisp,是否可以定义对序列中的特定元素(例如第一个)进行调度的方法?不使用“完全通用”的谓词调度机制是否可以做到这一点 下面我有一个程序,它以负范式重写命题演算中的一个表达式(即所有的否定出现在变量之前)。它还删除了除和和或之外的所有连接词,并用等效的定义替换它们 它大量使用方法,但我认为我没有充分利用对象系统 我希望能够基于当前表达式标题中的符号'和,'或,'not',imp',iff为规范化和规范化不提供一系列单独的defmethod案例 特别是,我希望能够写出类似于以下内容的东西 (defmeth
和
和或
之外的所有连接词,并用等效的定义替换它们
它大量使用方法,但我认为我没有充分利用对象系统
我希望能够基于当前表达式标题中的符号'和,'或,'not',imp',iff
为规范化
和规范化不
提供一系列单独的defmethod
案例
特别是,我希望能够写出类似于以下内容的东西
(defmethod normalize-all ((exprs ('and list)))
`(and ,@normalize-all (cdr exprs)))
作为一个独立的定义,当exprs
是一个列表,其中和作为其汽车
我现在只执行“顶级”类型检查,并在函数体中大量使用cond
(defmethod normalize-all ((exprs list))
(loop for x in exprs collecting (normalize x)))
(defmethod prepend-not-to-all ((exprs list))
(loop for x in exprs collecting (list 'not x)))
(defmethod normalize ((expr symbol))
expr)
(defmethod normalize-not ((expr symbol))
`(not ,expr))
(defmethod normalize ((expr cons))
(let
((head (car expr))
(tail (cdr expr)))
(cond
((eq head 'and)
`(and ,@(normalize-all tail)))
((eq head 'or)
`(or ,@(normalize-all tail)))
((eq head 'imp)
`(or
,(normalize `(not ,(first tail)))
,(normalize (second tail))))
((eq head 'iff)
`(and ,(normalize `(imp ,(first tail) ,(second tail)))
,(normalize `(imp ,(second tail) ,(first tail)))))
((eq head 'not)
(normalize-not (first tail))))))
(defmethod normalize-not ((expr cons))
(let
((head (car expr))
(tail (cdr expr)))
(cond
((eq head 'and)
`(or ,@(normalize-all (prepend-not-to-all tail))))
((eq head 'or)
`(and ,@(normalize-all (prepend-not-to-all tail))))
((eq head 'imp)
`(and
,(normalize (first tail))
,(normalize-not (second tail))))
((eq head 'iff)
`(or
(normalize-not `(imp ,(first tail) ,(second tail)))
(normalize-not `(imp ,(second tail) ,(first tail)))))
((eq head 'not)
(normalize (first tail))))))
(print (normalize '(iff a b)))
更一般地说,我试图模仿Haskell中的一种编写函数的风格,如下所示,因为案例很容易检查
f :: Int -> String -> Int
f 0 _ = ...
f 1 (x:xs) = ...
f n _ | n `mod` 2 == 0 = ...
| otherwise = ...
管道前出现的图案基于所涉及类型的结构。整数没有结构(n+k
patterns not count反正都不存在了),因此我们只能匹配特定的整数,用\u
忽略整数,或者用变量捕获它
任意布尔值表达式可以出现在|
之后,并控制rhs上的定义是否有效。(n`mod`2==0
检查一个数字是否为偶数,否则
仅为真
但读起来更好)
文本上较早的案例总是优先于文本上较晚的案例。而f
是封闭的,因为其定义的所有组件都必须出现在定义站点上。没有内置的方法来实现这一点。如果要模仿Haskell样式,可以使用模式匹配库,例如。但是,它不允许您以单独的顶级形式编写子句
;; Dependencies: (ql:quickload '(:fare-quasiquote :trivia :trivia.quasiquote))
(defpackage #:normalize
(:use #:cl #:named-readtables #:trivia)
(:export #:normalize #:imp #:iff))
(in-package #:normalize)
(in-readtable :fare-quasiquote)
(defun normalize-all (exprs)
(mapcar #'normalize exprs))
(defun prepend-not-to-all (exprs)
(mapcar (lambda (x) `(not ,x)) exprs))
(defun-ematch normalize (expr)
;; The body of DEFUN-EMATCH is a list of clauses starting with the
;; pattern and followed by a body of forms to execute when the
;; pattern matches the sole argument (formatted here for the sake of
;; readability with the pattern on the left and the body on the
;; right). The EMATCH variant signals an error if no pattern matches
;; the input.
((type symbol) expr)
(`(and ,@tail) `(and ,@(normalize-all tail)))
(`(or ,@tail) `(or ,@(normalize-all tail)))
(`(imp ,a ,b) `(or ,(normalize `(not ,a))
,(normalize b)))
(`(iff ,a ,b) `(and ,(normalize `(imp ,a ,b))
,(normalize `(imp ,b ,a))))
(`(not ,expr) (normalize-not expr)))
(defun-ematch normalize-not (expr)
((type symbol) `(not ,expr))
(`(and ,@tail) `(or ,@(normalize-all (prepend-not-to-all tail))))
(`(or ,@tail) `(and ,@(normalize-all (prepend-not-to-all tail))))
(`(imp ,a ,b) `(and ,(normalize a)
,(normalize-not b)))
(`(iff ,a ,b) `(or ,(normalize-not `(imp ,a ,b))
,(normalize-not `(imp ,b ,a))))
(`(not ,expr) (normalize expr)))
(normalize '(iff foo bar))
;=> (AND (OR (NOT FOO) BAR) (OR (NOT BAR) FOO))
或者,您可以使用另一个通用函数来处理列表。差不多
(defmethod normalize ((expression list))
(normalize-list (first expression)
(rest expression)))
(defmethod normalize-list ((operator (eql 'and)) arguments)
`(and ,@(normalize-all arguments)))
(defmethod normalize-list ((operator (eql 'or)) arguments)
`(or ,@(normalize-all arguments)))
;; ...
但这将比模式匹配更加冗长。请参见