将 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)))))
关于这个的几个问题:
- 我怎样才能消除将
n
(当前索引增量)传递给函数的需要?我需要围绕它有一个包装函数吗?或者通常的方法是什么?
- 除此之外,它还能formatted/made更干净吗?
我想实现它的一种方法 '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 方言支持,请使用
add1
将 1
添加到数字中。
最后但并非最不重要的一点是,检查您的口译员是否已经为您想要做的事情提供了程序;例如:在 Racket 中我们有 index-of
做同样的事情。
我正在学习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)))))
关于这个的几个问题:
- 我怎样才能消除将
n
(当前索引增量)传递给函数的需要?我需要围绕它有一个包装函数吗?或者通常的方法是什么? - 除此之外,它还能formatted/made更干净吗?
我想实现它的一种方法 '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 方言支持,请使用
add1
将1
添加到数字中。
最后但并非最不重要的一点是,检查您的口译员是否已经为您想要做的事情提供了程序;例如:在 Racket 中我们有 index-of
做同样的事情。