如何根据Scheme / Racket中的条件实际定义很多东西?

时间:2017-07-20 10:03:29

标签: scheme racket

我在Racket工作,但据我所知,这是一般的方案;你不能做这样的事情,因为我们试图在表达式上下文中定义一些东西:

(if condition
    (define x "do a backflip")
    (define x "do a barrel roll"))

现在对于这个特例,我可以做一些这样的事情:

(define x
  (if condition
      "do a backflip"
      "do a barrel roll"))

但如果你有很多不同的东西要定义,这真的很糟糕,因为而不是

(if condition
    (begin (define x "do a backflip")
           (define y "awesome")
           (define z "shoot me"))
    (begin (define x "do a barrel roll")
           (define y "nice")
           (define z "give me sweet release")))

我们得到了

(define x                                                                                                                                                                                                                                      
  (if condition
      "do a backflip"
      "do a barrel roll"))
(define y                                                                                                                                                                                                                                      
  (if condition
      "awesome"
      "nice"))
(define z                                                                                                                                                                                                                                      
  (if condition
      "shoot me"
      "give me sweet release"))

这不是DRY,我们不断重复condition的测试。结果是,如果我们不想测试condition我们要检查other-condition,我们必须对n次{}进行更改。有没有更好的方法来做到这一点,如果是这样的话:怎么样?

2 个答案:

答案 0 :(得分:5)

使用define-values

(define-values (x y z) (if condition
                           (values "do a backflip"    "awesome" "shoot me")
                           (values "do a barrel roll" "nice"    "give me sweet release")))

答案 1 :(得分:4)

如果"很多"非常大,您可能想要使用Racket的units

首先使用您要定义的所有变量定义签名

(define-signature acro^ (x y z))

然后定义包含不同定义集的单位

(define-unit flippy@
  (import) (export acro^)
  (define x "do a backflip")
  (define y "awesome")
  (define z "shoot me"))

(define-unit rolly@
  (import) (export acro^)
  (define x "do a barrel roll")
  (define y "nice")
  (define z "give me sweet release"))

您可以动态选择调用的单位并绑定到签名中的名称:

(define-values/invoke-unit
  (if .... flippy@ rolly@)
  (import) (export acro^))

x
;; => either "do a backflip" or "do a barrel roll", depending on condition