2017-04-30 46 views
1

对于Scheme编程语言来说,我是一个相当新的东西,我只是无法弄清楚这两段代码之间的区别,特别是我指出的那些代码段。Scheme null?声明

;program that returns the Nth element in a list where N is an integer argument 

(define getElement 
(lambda (N L) 
(cond 
    ((null? L) '()) 
    ((= N 1) (car L)) 
    (#t(getElement (- N 1) (cdr L)));this line 
) 
) 
) 

;takes a list L and a number N and returns the list L but with the first N elements removed 
(define remove 
(lambda (N L) 
(cond 
    ((null? L) '()) 
    ((= N 0) L) 
    (#t(remove (- N 1) (cdr L)));and this line 
) 
) 
) 

为什么这些程序的输出如此不同?除了检查列表是否为空以及整数N是否为特定值之外,我无法看到条件语句对程序输出后2行有什么影响,请执行此操作。

这是我的第一篇文章,所以任何的建议是值得欢迎的

回答

2

两个功能是递归的并使用相同的递归策略。但是,当你到达递归的底部时,他们会做出非常不同的事情。

每个函数都将n减1,并将列表减少一个元素,并在新的上下文中调用它自己。 所以,在这两种情况下,列表(至少在函数的参数中表示的)不断缩短。 remove函数返回整个剩余列表。由于在remove函数的参数中已经从列表的副本中删除了一些元素,因此这会返回一个缩短的列表。 但是,第n个元素函数不返回列表;它返回(car l),或返回l中包含的cons单元中的元素。也就是说,它只返回列表的当前元素。 这就是他们产生不同结果的原因。

0

您表示的行也是一样的。 绝对没有区别!它递归到自身,索引减少,列表更改为cdr

当基本情况命中第一个返回第一个元素,第二个返回列表。

(getElement 1 '(1 2 3)) ; ==> 1, Since it does (car L) 
(remove 0 '(1 2 3))  ; ==> (1 2 3), since it does L 

现在,如果你getElement工作就像list-ref0应该已经基本情况,同为remove。当索引为零之前列表为空时,它也应该发出一个错误信号。这是更喜欢它:

#!r6rs 
(import (rnrs)) 
(define (my-list-ref lst pos) 
    (cond ((null? lst) (raise 'list-too-short)) 
     ((zero? pos) (car lst)) 
     (else (my-list-ref (cdr lst) (- pos 1))))) 

(my-list-ref '() 1) 
; ==> uncaught exception: list-too-short 
1

正如你所说,

如果整数N有一定的价值,这样做

不同的是,在“做” 。

第一个,

((= N 1) (car L)) 

说:“得到一个列表的第一个元素,以列表的car”。

第二个,

((= N 0) L) 

说:“用来删除列表中没有的元素,返回整个列表”。

的递归完全一样,但第一个写着“从列表中的cdr获得元素N - 1”,而第二个写着“从列表中删除的cdrN - 1元素”。

(它看起来像第一功能已经从Lisp语言,其中nil是“假y”的翻译。更计划-Y函数将返回#f。)