【问题标题】:Common Lisp - Pattern MatchingCommon Lisp - 模式匹配
【发布时间】:2020-05-07 18:32:31
【问题描述】:

我正在尝试编写一个函数来比较 Common Lisp 中的两个列表。

符号“&”表示任意元素序列,符号“$”表示任意单个元素。

(defun match (filter data)
     (cond
        ((atom filter) (eq filter data))
        ((atom data) NIL)
        ((eq (car filter) '|$|)
           (match (cdr filter) (cdr data)))
        ((eq (car filter) '|&|)
           (cond
             ((match (cdr filter) data))
             (data (match filter (cdr data)))))
        ((match (car filter) (car data))
            (match (cdr filter) (cdr data)))))

效果很好:

(match '(a b c) '(a b c)) ; => T
(match '(a $ c) '(a b c)) ; => T
(match '(a ff c) '(a b c)) ; => NIL
(match '(a & c) '(a z b c)) ; => T

我想添加一个新的过滤器(带有 % 符号),它允许在不同的可能元素之间进行选择,例如

(match '(a %(b 1) c) '(a b c)) ; => T
(match '(a %(b 1) c) '(a 1 c)) ; => T
(match '(a %(b 1) c) '(a z c)) ; => NIL

【问题讨论】:

    标签: functional-programming pattern-matching common-lisp clisp


    【解决方案1】:

    您必须尝试 % 之后的子列表中的所有元素,以查看其中是否有任何元素与过滤器的其余部分相匹配:

    (defun match (filter data)
         (cond
            ((atom filter) (eq filter data))
            ((atom data) NIL)
            ((eq (car filter) '|$|)
               (match (cdr filter) (cdr data)))
            ((eq (car filter) '|&|)
               (cond
                 ((match (cdr filter) data))
                 (data (match filter (cdr data)))))
            ((eq (car filter) '|%|)
              (some #'(lambda (f) (match (cons f (cddr filter)) data)) (cadr filter)) )
            ((match (car filter) (car data))
                (match (cdr filter) (cdr data)))))
    

    您还应该添加一些检查步骤以确保过滤器的格式正确,即 % 之后的元素是列表等...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-27
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      相关资源
      最近更新 更多