搭配搭配缩短

时间:2018-11-26 12:33:47

标签: scheme racket

如何用匹配项替换if语句,使代码更易于阅读和理解?

(: f (t1 -> integer))
(define f
(lambda (x)
   (if (natural? (t1-b x))
       (+ (t1-a x)
          (t1-b x)
          (t1-c x))
       (if (and (= (t2-e (t1-b x)) 1)
                (= (t2-d (t1-b x)) 1))
           10
           (- (+ (t2-d (t1-b x))
                 (t2-e (t1-b x)))
              (t1-a x))))))

2 个答案:

答案 0 :(得分:1)

这不是match的好用例,因为条件不适合用于模式匹配。但是我们可以使用cond简化嵌套条件:

(define (f x)
  (cond ((natural? (t1-b x))
         (+ (t1-a x)
            (t1-b x)
            (t1-c x)))
        ((and (= (t2-e (t1-b x)) 1)
              (= (t2-d (t1-b x)) 1))
         10)
        (else
         (- (+ (t2-d (t1-b x))
               (t2-e (t1-b x)))
            (t1-a x)))))

答案 1 :(得分:0)

您没有提供t1t2的结构定义,所以我会猜测。

(struct t1 [a b c] #:transparent)
(struct t2 [d e] #:transparent)

假设这些定义与您的定义相符,我可以翻译每个分支问题和答案。

分支1,使用?模式的条件,命名为消除选择器

第一个分支条件(natural? (t1-b x))可以转换为

(t1 _ (? natural?) _)

?模式将谓词应用于与其匹配的值,并且仅在谓词返回true时才匹配。要查找其文档,请在match documentation中搜索(? expr pat ...)

而且,由于在分支答案中使用了选择器t1-at1-bt1-c,因此可以命名它们

(t1 a (? natural? b) c)

整个分支看起来像

[(t1 a (? natural? b) c)
 (+ a b c)]

第2条,使用文字模式,例如1

第二个分支条件

(and (= (t2-e (t1-b x)) 1)
     (= (t2-d (t1-b x)) 1))

可以翻译为

(t1 _ (t2 1 1) _)

而且,由于您在分支答案中未使用任何选择器,因此无助于命名通配符,并且整个问题答案对都可以翻译为

[(t1 _ (t2 1 1) _)
 10]

分支3,消除了从内而外嵌套的选择器

对于这个,没有分支问题,但是主体中使用了选择器:

(- (+ (t2-d (t1-b x))
      (t2-e (t1-b x)))
   (t1-a x))))

首先在t1上删除x的选择器:

[(t1 a b _)
 (- (+ (t2-d b)
       (t2-e b))
    a)]

然后在t2上删除b的选择器:

[(t1 a (t2 d e) _)
 (- (+ d e)
    a)]

放在一起

将三个分支放在正文中的(match x branch1 branch2 ...)

; assuming these struct definitions
(struct t1 [a b c] #:transparent)
(struct t2 [d e] #:transparent)

(: f (t1 -> integer))
(define f
  (lambda (x)
    (match x
      [(t1 a (? natural? b) c)
       (+ a b c)]
      [(t1 _ (t2 1 1) _)
       10]
      [(t1 a (t2 d e) _)
       (- (+ d e)
          a)])))