Scheme 开关语句语法

Scheme Switch-Statement Syntax

在 Scheme 中创建 switch 语句的最聪明的方法是什么?

我想将一个值与其他几个值进行比较,如果一个结果为真,则整个函数的结果应该为真,否则为假。我对scheme中的语法不是很好。

在 Scheme 中你有 case:

(case (car '(c d))
  ((a e i o u) 'vowel)
  ((w y) 'semivowel)
  (else 'consonant)) ; ==> consonant

如您所见,它与文字数据进行了比较。因此,您不能将该值与其他变量进行比较。那么你需要cond

对每个值进行显式比较的替代方法是使用 member:

> (define (vowel? x) (member x '(a e i o u))
> (vowel? 'b)
#f

基本案例

通常,如果您想 return 一个布尔值,一个简单的布尔表达式就足够了。在简单的情况下,or 中的几个检查就足够了:

(define (switch val)
  (or (equal? val 'some-value)
      (equal? val 'some-other-value)
      (equal? val 'yet-another-value)))

高阶函数

我们是否经常这样做,工作量很大,所以我们可以创建一个名为 make-switch 的函数,它接受一个值列表,而 returns 是一个用作 switch 语句的函数对于这些值:

(define (make-switch list-of-vals)
  (define (custom-switch val)
    (define (inner vals)
      (cond ((null? vals) #f)
            ((equal? val (first vals)) #t)
            (else
             (inner (rest vals)))))
    (inner list-of-vals))

然后我们可以这样使用make-switch

> (define k (make-switch '(1 2 a "b")))
> (k 1)
#t
> (k 5)
#f
> (k "a")
#f
> (k "b")
#t

更快的查找

如果我们主要检查一组静态值,那么哈希-table 是另一种选择。 #lang racket 中的代码显示了一般方法,R5RS 方案可以使用 SRFI-69:

#lang racket
(define (make-switch alist)
  (define (list->hash alist)
    (make-hash (map (lambda (x) (cons x x))
                    alist)))
  (lambda (val)
    (if (hash-ref (list->hash alist) val #f)
        #t
        #f)))

备注

在某些情况下,您可能想使用 eq? 或其他一些相等性测试,但我已将 make-custom-make-switch 作为进一步探索的练习。