我的问题是将嵌套的if条件重写为具有本地绑定的分支的单个cond
。我对Racket很新,只是迈出了我的第一步,所以如果我的问题很愚蠢,请宽容。
简而言之,任务是编写一个带矢量并在其中搜索值的函数。向量包含混合的东西 - 对和非对。感兴趣的价值应该是一对的车。
工作解决方案使用带有嵌套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))]))])
这就是我最多取得的成果:在test-expr中调用(vector-ref vec pos)
和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
如何进一步在test-expr和result-expression之间共享el
?
我希望el
保持在这个特定的cond分支的本地。
以下代码工作不正确。 AFAIU,整个letrec
表达式是
被视为cond的文本expr?
(cond
[(= pos vlen) #f]
[(letrec ([el (vector-ref vec pos)])
(and (pair? el) (equal? v (car el)))
el)]
[#t (find-in-vector (+ 1 pos))])
答案 0 :(得分: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>)
子句。这里,生成器是创建一个公共值以供 guard 和 receiver 使用的东西。在这种情况下,我们的接收器只是values
,它返回给定的值而不进行任何处理。
更新:目前srfi/61
对于使用#lang racket
之类的程序无法正常运行(srfi/61
正在使用=>
的不同绑定和else
提供的racket/private/cond
。这已经recently fixed,并且应该出现在未来的Racket版本中。