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)))

;; ...
但这将比模式匹配更加冗长。

请参见