1

cond我的问题是关于将嵌套的 if 条件重写为具有本地绑定的分支的单个条件。我对球拍很陌生,只是迈出了第一步,所以如果我的问题很愚蠢,请宽容。

简而言之,任务是编写一个函数,该函数接受一个向量并在其中搜索一个值。向量包含混合的东西——对和非对。感兴趣的价值应该在一对汽车中。

工作解决方案使用带有嵌套 ifs 的递归辅助函数

[vlen (vector-length vec)]
[find-in-vector
(lambda (pos)
 (if (= pos vlen)                               ;; if the end of the vector has been reached
     #f                                         ;; then return false
     (let ([el (vector-ref vec pos)])           ;; Otherwise, extract current element from the vector,
       (if (and (pair? el) (equal? v (car el))) ;; if the element is a pair and its car is what we want
           el                                   ;; then return the element
           (find-in-vector (+ 1 pos))))))]      ;; otherwise keep searching the vector

我想重写它,使它cond看起来更紧凑。下面的代码是一个可能的实现。问题是(vector-ref vec pos) 计算了几次,这就是我想重写的,这样它只计算一次,就像在前面的嵌套 ifs 实现中一样

[vlen (vector-length vec)]
[find-in-vector
 (lambda (pos)
   (cond [(= pos vlen) #f]
         [(and (pair? (vector-ref vec pos))            ;; one
               (equal? v (car (vector-ref vec pos))))  ;; two
          (vector-ref vec pos)]                        ;; three is too many
         [#t (find-in-vector (+ 1 pos))]))])

这就是我最多取得的成就:一次调用(vector-ref vec pos)test-expr ,另一次调用 result-expr

(cond
  [(= pos vlen) #f]
  [(letrec ([el (vector-ref vec pos)])      ;; extract current element from the vector
     (and (pair? el) (equal? v (car el))))  ;; and use it in conditionals
   (vector-ref vec pos)]                    ;; again, extract and return. FIXIT
  [#t (find-in-vector (+ 1 pos))]))])       ;; otherwise, keep searching

如何进一步el在 test-expr 和 result-expression 之间进行共享?我想el留在这个特定的 cond 分支的本地。下面的代码工作不正确。AFAIU,整个letrec表达式被视为条件的文本表达式?

(cond
 [(= pos vlen) #f]
 [(letrec ([el (vector-ref vec pos)])
    (and (pair? el) (equal? v (car el)))
    el)]
 [#t (find-in-vector (+ 1 pos))])
4

1 回答 1

1

如果您先导入SRFI 61 ,则可以这样做:

(require srfi/61)
(define (find-in-vector vec v)
  (define vlen (vector-length vec))
  (let loop ((pos 0))
    (cond
      ((= pos vlen) #f)
      ((vector-ref vec pos)
       (lambda (el) (and (pair? el) (equal? v (car el))))
       => values)
      (else (loop (add1 pos))))))

SRFI 61 提供的重要一点是它允许该(<generator> <guard> => <receiver>)子句。在这里,生成器是创建一个供保护器和接收器使用的公共值的东西。在这种情况下,我们的接收器是简单values的,它返回它给出的值而不进行任何处理。


更新:目前srfi/61对于使用等的程序不能正常工作#lang racketsrfi/61正在使用不同的绑定=>else来自racket/private/cond提供的绑定)。这最近已修复,应该会出现在未来的 Racket 版本中。

于 2013-02-27T10:28:20.677 回答