删除列表的第n个元素

时间:2017-01-25 20:24:03

标签: scheme

您好我编写了以下过程来删除列表的第n个元素

  (define  (delete l n)
     (if (= n 1)
      (begin (set! l (cdr l) )
             l)
      (begin ( set-cdr! (n_sub_list (- n 1 ) l )
                         (cdr (n_sub_list n l )))
          l)))

           (define n_sub_list n l )
                  (if (= n 1) l
                (n_sub_list ( - n 1 ) (cdr l ))))

如果我这样做(定义d'(1 2 3 4))和(删除!d 2)我得到的是d(1 3 4)但如果我继续做(删除!d 1)我得到(1 3 4)这是错误的,任何想法为什么?

1 个答案:

答案 0 :(得分:1)

在你的代码中,你有两个不同的程序可以改变某些东西。

您有set-cdr!更改参数中对的cdr指向的内容。这只能发生在可变的列表上。 '(1 2 3 4)是一个不可变列表,因此结果未定义。在(list 1 2 3 4)上这样做是可以的,因为它变成了一个可变列表。

set!重新定义了命名变量所代表的内容。它不会更改名称实际指向的值。只是标签l表示除了之前的值之外的其他值,由于d仍在您的案例中引用它,因此仍然存在。

就像我打电话给我的朋友新手一样,半年后我停下来开始给另一位朋友打电话。我的原始朋友不会停止存在或成为我的另一个朋友而另一个朋友不会接管他的生命。唯一真正的变化是persion与昵称相关联。这就是set!的作用。

它只与最接近的同名:

(define a 5)
(define b 10)
(let ((a 10))
  (set! b 20)
  (set! a 20)
  a)
; ==> 20
b
; ==> 20
a
; ==> 5 

a更改为let中的本地更改,使全局a保持不变。

计划程序不应该改变,所以你返回的是重要的:

(define (delete l n)
  (cond ((or (null? l) (< n 1)) l)
        ((= n 1) (cdr l))
        (else (cons (car l)
                    (delete (cdr l)
                            (- n 1))))))

(set! d (delete d 1))