问题描述
我正在尝试在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))]))]))