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

问题描述

我正在尝试在Scheme中创建自己的模式匹配系统。首先,我将为s表达式创建一个解析器,将其分成这样的标记

'(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,后者是{{1}的参数}。
  • 第二,这里根本不需要宏。我怀疑您可能在想,因为您要尝试编写宏,所以必须在其构造中使用宏:这不一定是正确的,而且通常是一个坏主意。
  • 第三,您的classify-sexpr的语法无法修复:我无法弄清它的作用。
  • 最后,永远不需要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
  `((,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))]))]))