将 python 方法转换为方案过程

Converting a python method into a scheme procedure

我正在学习scheme,基本上是先写方法,在python中写那个方法(递归),然后把它翻译成scheme。例如,这里尝试写一个列表索引位置:

def idx(elem, l, n=0):
    "Recursive routine for [1,2,3].index(2)"
    if not l:
        return -1
    else:
        return n if (l[0] == elem) else idx(elem, l[1:], n+1)

idx(2, [1,2,3])
# 1

翻译它:

(define (get-idx elem List n)
  (if (= (length List) 0) -1 
  (if 
    (equal? (car List) elem) 
    n
    (get-idx elem (cdr List) (+ n 1)))))

关于这个的几个问题:

我想实现它的一种方法 'cleaner' 可能是:

(define (get-idx-internal elem List n)
  (if (= (length List) 0) -1 
    (if (equal? (car List) elem) n
      (get-idx-internal elem (cdr List) (+ n 1)))))

(define (get-idx elem List) (get-idx-internal elem List 0))
(display (get-idx 3 (list 1 2 3 4 5)))

; 2

解决您的第一个问题:您的方法很好,在 Scheme 中,我们传递在递归调用期间作为参数修改的值。一些方言(如 Racket)支持 optional arguments,因此我们可以像在 Python:

中那样声明过程
; now it's not necessary to pass `n` when calling it
(define (get-idx elem lst [n 0])

为了使其更加地道,我们可以这样重写您的解决方案:

(define (get-idx elem lst [n 0])
  (cond ((null? lst) -1)
        ((equal? (car lst) elem) n)
        (else (get-idx elem (cdr lst) (add1 n)))))
  • 使用 cond 比嵌套 if 表达式更简单。
  • 使用 length 检查列表是否为空是一个很大的禁忌(它将遍历整个列表,使您的算法成为二次方!),请改用 null?
  • 不要调用参数 list,有一个同名的内置过程。
  • 如果您的 Scheme 方言支持,请使用 add11 添加到数字中。

最后但并非最不重要的一点是,检查您的口译员是否已经为您想要做的事情提供了程序;例如:在 Racket 中我们有 index-of 做同样的事情。