不能在子句中使用表达式进行球拍模式匹配吗?

时间:2018-11-30 09:40:55

标签: pattern-matching racket

在球拍中,我编写了这段基本代码。但是球拍似乎不喜欢第一个子句-尝试运行此子句,我得到错误“ match:模式语法错误:(-3 9)”

(define/match (prob i)
    [((- 3 9)) 0]
    [(_) 4]
)

奇怪的是,如果我不是使用减法程序,而是使用“列表”程序(即((list 3 9))而不是((-3 9))),则代码可以正常工作。有什么作用?

1 个答案:

答案 0 :(得分:1)

如果您的目标是检查参数i是否等于(-3 9)解析出的值,则问题是Racket match形式不接受任意表达式作为模式。有关match表单可以使用哪种模式的更多信息,请查看Pattern Matching上的Racket文档(如您所见,您可能会注意到(list ...)包含在允许的模式中) !)。但是,简单的答案(如Alex Knauth所说)是将(- 3 9)替换为(== (- 3 9))

另一方面,如果您的目标是检查提供给(prob i)的自变量是否实际上是表达式(-3 9),则不管其计算结果如何,define/match都不会满足。球拍功能为pass by value。因此,当有人将表达式作为参数i传递到您的prob函数时,i等于该表达式的求值结果,即

(define (some-function some-argument)
    some-argument) ; we just get the number 3 for some-argument
                   ; and have no way of knowing via this function
                   ; that someone actually passed us the expression
                   ; (- (- 9 1) 5)

(some-function (- (- 9 1) 5))

我们将不得不使用称为macro的其他工具。在对符号求值之前,宏会对程序的文本进行操作。您的(prob i)函数的宏实现将在REPL上像这样工作:

> (define-syntax-rule (prob i)
    (if (equal? 'i '(- 3 9))
      0
      4))
> (prob (- 3 9))
0
> (prob -6)
4
> (prob 78)
4

这称为“语法规则”。它引用了参数i,然后将其与带引号的表达式(- 3 9)进行比较,以查看是否以i的形式提供。让我知道您是否还有任何问题!祝你好运!