我在Scheme中找到了以下Binary Search的实现:
(define (binary-search value vector)
(let helper ((low 0)
(high (- (vector-length vector) 1)))
(if (< high low)
#f
(let ((middle (quotient (+ low high) 2)))
(cond ((> (vector-ref vector middle) value)
(helper low (- middle 1)))
((< (vector-ref vector middle) value)
(helper (+ middle 1) high))
(else middle))))))
根据评论中的内容,上面的函数使用tail-recursion来调用help函数。我想知道这是否像GOTO指令一样,因为我没有看到有一个正确的&#34;递归&#34;调用二进制搜索功能。
在这种情况下,可以说它像goto指令一样工作吗?
答案 0 :(得分:2)
您所看到的内容称为let
。 (如果你有点好奇的话,我写了blog post about how named let
works。)你所拥有的代码完全相同:
(define (binary-search value vector)
(define (helper low high)
(if (< high low)
#f
(let ((middle (quotient (+ low high) 2)))
(cond ((> (vector-ref vector middle) value)
(helper low (- middle 1)))
((< (vector-ref vector middle) value)
(helper (+ middle 1) high))
(else middle)))))
(helper 0 (- (vector-length vector) 1)))
换句话说, 在helper
而不是binary-search
上进行尾递归。但尾递归正在发生。
有些人会想到像goto
这样的尾递归,但我不认为这是一个有用的比较。两者之间唯一的共同点是你可以使用尾递归实现循环,就像使用goto
一样。但是相似之处到此为止:尾递归是一种特殊的递归(其中当前的调用帧被尾调用替换),但它仍然是递归; goto
跳转到代码中的任意一点,但它是一个完全必要的操作,与递归无关。
答案 1 :(得分:0)
让我们只是lambdas的语法糖。例如:
(let ((i 2)
(j 5)
(* i j))
相当于
((lambda (i j) (* i j)) 2 5)
代码中的let称为let,因为您为它提供了标签。所以基本上,你伪装的lambda绑定了一个名字。从这个意义上说,它是一个转到。但是,您需要在let的范围内才能“跳转”到它。该函数是尾递归的,因为您没有推迟任何计算。在任何时间点,您只需要i和j的当前值就可以继续计算。