【问题标题】:Pattern Matching of expressions表达式的模式匹配
【发布时间】:2020-04-29 00:13:40
【问题描述】:

我希望你能帮助我一点。对于作业,我应该编写一个函数,该函数使用模式匹配检查表达式是否对应于某个结构定义。

这些是定义:

(define-struct literal (value))
(define-struct addition (lhs rhs))
(define-struct subtraction (lhs rhs))
(define-struct multiplication (lhs rhs))
(define-struct division (lhs rhs))

我的代码开头如下:

; An Expression is one of:
; - (make-literal Number)
; - (make-addition Expression Expression)
; - (make-subtraction Expression Expression)
; - (make-multiplication Expression Expression)
; - (make-division Expression Expression)
; interp. abstract syntax tree of arithmetic expressions

(define EXPRESSION-1 (make-literal 42))

(define EXPRESSION-2
  (make-addition (make-literal 4) (make-multiplication (make-literal 5) (make-literal 8))))

(define EXPRESSION-3
  (make-division (make-subtraction (make-literal 11) (make-literal 7)) (make-literal 2)))


; Any -> Boolean
; checks whether e is an Expression
(check-expect (expression? EXPRESSION-1) #true)
(check-expect (expression? EXPRESSION-2) #true)
(check-expect (expression? (make-literal "42")) #false)
(define (expression? e)
  (match e
    [(and (literal?) (number? literal-value)) #true]
    [(and (addition?) (number? addition-lhs) (addition-rhs)) #true]
    [substraction? #true]
    [multiplication? #true]
    [division? #true]
    [... #false]   
))

我这样做的原因是因为我必须检查表达式是否属于结构,并且我还必须确保该结构的元素只是数字,因为第二次测试会失败。 但不知何故,我的方法不起作用,因为对 EXPRESSION-1 和 EXPRESSION-2 的测试已经失败,我无法直起头,为什么......

我把下面的四行保留原样,因为我想把重点放在加法上,因为我希望这将是“加法?”行的简单重复。 你将如何着手做到这一点? 另外,您是否建议将此检查作为结构元素的数字外包到单独的函数中?

干杯!

编辑: 现在,正如我认为我明白了,我正在努力完成下一个任务,我相信它必须以与下面的 Atharva Shukla 建议的方式几乎相同的方式工作。任务是将表达式转换为 s 表达式,例如从 (make-addition (make-literal 1) (make-literal 2)) 到 '(+ 1 2) 也使用模式匹配。

; Expression -> S-Expression
; converts an expression into the corresponding S-Expression
(check-expect (expr->sexpr EXPRESSION-1) '42)
(check-expect (expr->sexpr EXPRESSION-2) '(+ 4 (* 5 8)))
(check-expect (expr->sexpr EXPRESSION 3) '(/ (- 11 7) 2))
(check-expect (expr->sexpr (make-addition (make-literal 1) (make-literal 2)) 
'(+ 1 2))
(define (expr->sexpr e)
(match e
[(literal value) 'value]
[(addition lhs rhs) '(+ (addition lhs) (addition rhs))]
[(subtraction lhs rhs) '(- (subtraction lhs) (subtraction rhs))]
[...]
[...]
))

【问题讨论】:

标签: data-structures pattern-matching racket


【解决方案1】:

模式中指定的字段名称将绑定在它们各自的子句中。所以不需要谓词。

(define (expression? e)
  (match e
    [(literal v) (number? v)]
    [(addition l r) (and (expression? l) (expression? r))]
    [(subtraction l r) (and (expression? l) (expression? r))]
    [(multiplication l r) (and (expression? l) (expression? r))]
    [(division l r) (and (expression? l) (expression? r))]
    [_ #false]))

最后一个子句是通配符,即评估 RHS 的任何值。

第 2-5 条的相同 RHS 可以抽象如下:

(define (expression? e)
  (match e
    [(literal v) (number? v)]
    [(or (addition l r) (subtraction l r)
         (multiplication l r) (division l r))
     (and (expression? l) (expression? r))]
    [_ #false]))

但我更喜欢第一个版本,因为它反映了 Expression 的定义。

2020 年 12 月 1 日编辑:

这与前面的示例类似,但我们在进行时构建列表。

(check-expect (compile-expression EXPRESSION-1) 42)
(check-expect (compile-expression EXPRESSION-2) `(+ 4 (* 5 8)))
(check-expect (compile-expression EXPRESSION-3) `(/ (- 11 7) 2))

(define (compile-expression e)
  (match e
    [(literal v) v]
    [(addition l r) (list '+ (compile-expression l) (compile-expression r))]
    [(subtraction l r) (list '- (compile-expression l) (compile-expression r))]
    [(multiplication l r) (list '* (compile-expression l) (compile-expression r))]
    [(division l r) (list '/ (compile-expression l) (compile-expression r))]
    [_ (error "Not an Expression")]))

我更喜欢这个版本,因为它可以让您轻松创建更复杂的结构:

(define (compile-expression e)
  (match e
    [(literal v) v]
    [(addition l r) `(+ ,(compile-expression l) ,(compile-expression r))]
    [(subtraction l r) `(- ,(compile-expression l) ,(compile-expression r))]
    [(multiplication l r) `(* ,(compile-expression l) ,(compile-expression r))]
    [(division l r) `(/ ,(compile-expression l) ,(compile-expression r))]
    [_ (error "Not an Expression")]))

您可以了解更多关于引用、准引用和取消引用here

【讨论】:

  • 非常感谢您的回复,它确实帮助我更好地理解了模式匹配,并且我还能够创建一个计算实际算术表达式的函数。但是现在,正如我以为我明白了一样,我正在为下一个任务而苦苦挣扎,我相信它必须以几乎相同的方式工作。任务是将表达式转换为 s 表达式,例如从 (make-addition (make-literal 1) (make-literal 2)) 到 '(+ 1 2) 也使用模式匹配。我会在另一条评论中发布代码,也许你又有一点提示?
猜你喜欢
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多