Chez Scheme 的自定义模式匹配工具

Custom pattern-matching facility for Chez Scheme

我正在尝试在 Scheme 中制作自己的模式匹配系统。首先,我正在为 s-expressions 创建一个解析器,将它们分成这样的标记:

'(1 2 b (3 4)) => '(number number symbol (number number))

应该注意的是,我之前没有在 Scheme 中使用过 define-syntax,所以这可能是我搞砸的地方。 Chez Scheme 抛出这个错误: Exception: invalid syntax classify at line 21, char 4 of pmatch.scm。请注意,行号不会与此处的代码片段完全对应。有谁知道我做错了什么?

(define-syntax classify
  (syntax-rules ()
    ((_ checker replacement)
     ((checker (car sexpr)) (cons replacement (classify-sexpr (cdr sexpr)))))))

(define (classify-sexpr sexpr)
    (cond
        ((null? sexpr) sexpr)
        (classify list? (classify-sexpr (car sexpr)))
        (classify number? 'number)
        (classify symbol? 'symbol)
        (else
          (cons 'symbol (classify-sexpr (cdr sexpr))))))

(display (classify-sexpr '(1 (b 3) (4 5) 6)))

您的代码非常混乱。事实上,它太混乱了,我完全不确定你到底想做什么:我的回答是基于你所说的分类器在你的问题开始时应该产生的结果。

  • 首先,你的宏引用了sexpr,它在宏中没有任何意义,因为Scheme宏是卫生的,它肯定不会引用sexpr,它是[=的参数16=].
  • 其次,您在这里根本不需要宏。我怀疑您可能在想,因为您正在尝试 编写 一个宏,所以您必须在其构造中使用宏:这不一定是正确的,而且通常是个坏主意。
  • 第三,你的 cond 的语法是拙劣的无法修复:我无法理解它试图做什么。
  • 最后 list 分类将不再需要:如果您想将 (1 2 3 (x)) 分类为 (number number number (symbol)) 那么您将永远不会遇到您拥有列表的情况想要分类,因为你必须走进它才能对其元素进行分类。

而不是只写明显的函数做你想做的事:

(define classification-rules
  ;; an alist of predicate / replacement which drives classigy
  `((,number? number)
    (,symbol? symbol)))
    
(define (classify thing)
  ;; classify thing using classification-rules
  (let loop ([tail classification-rules])
    (cond [(null? tail)
           'something]
          [((first (first tail)) thing)
           (second (first tail))]
          [else
           (loop (rest tail))])))

(define (classify-sexpr sexpr)
  ;; classify a sexpr using classify.
  (cond
    [(null? sexpr) '()]
    [(cons? sexpr) (cons (classify-sexpr (car sexpr))
                         (classify-sexpr (cdr sexpr)))]
    [else (classify sexpr)]))

现在

> (classify-sexpr '(1 2 3 (x 2) y))
'(number number number (symbol number) symbol)

可能您真正想要的是将(1 2 (x 2))分类为(list number number (list symbol number))的东西。你可以很容易地做到这一点:

(define atomic-classification-rules
  ;; an alist of predicate / replacements for non-conses
  `((,number? number)
    (,symbol? symbol)))
    
(define (classify-sexpr sexpr)
  (cond
    [(null? sexpr) '()]
    [(list? sexpr)
     `(list ,@(map classify-sexpr sexpr))]
    [(cons? sexpr)
     `(cons ,(classify-sexpr (car sexpr))
            ,(classify-sexpr (cdr sexpr)))]
    [else
     (let caloop ([rtail atomic-classification-rules])
       (cond [(null? rtail)
              'unknown]
             [((first (first rtail)) sexpr)
              (second (first rtail))]
             [else
              (caloop (rest rtail))]))]))

现在

> (classify-sexpr '(1 2 3 (x 2) y))
'(list number number number (list symbol number) symbol)
> (classify-sexpr '(1 2 3 (x 2) . y))
'(cons number (cons number (cons number (cons (list symbol number) symbol))))