将元素添加到列表

时间:2017-11-06 03:14:42

标签: scheme racket r5rs

我正在尝试在Scheme中实现一个过程,该过程将位置x的元素i添加到现有列表中。这就是我想出的:

(define empty-list '())
(define (add i x L)
  (cond ((null? L) (set! L (list x)))
        ((= i 0)(set! L (cons x L)))
        (else (set! L (cons (car L)
                             (add (- i 1) x (cdr L))))
      )))

(add 0 1 empty-list) -> returns ()
(add 1 2 empty-list) -> returns ()
(add 2 3 empty-list) -> returns ()

代码不会更新现有列表。但是,如果我只是跑 (set! empty-list (list 1))(set! empty-list (cons 2 empty-list))它运作正常。 我正在努力去理解我做错了什么。

2 个答案:

答案 0 :(得分:0)

使用set!时,您不会更改实际值,但会使用新值分配最具体的绑定。在JavaScript中,它的工作方式相同:

function add (arr, element) {
  arr = arr.concatenate([element]);
  return arr;
}

const test = [1, 2, 3];
add(test, 4); // => [1, 2, 3, 4]
test;         // => [1, 2, 3]

Scheme中的这些程序通常不会发生变异。如果您使用该值删除set!,则会返回正确的值:

(define (add i x L)
  (cond 
    ((null? L) (list x)) ; might not be at correct position
    ((= i 0) (cons x L))
    (else (cons (car L) (add (- i 1) x (cdr L))))))

(add 1 'b '(a c)) ; ==> (a b c)

答案 1 :(得分:0)

在Scheme中,与许多函数式语言一样,我们通过使用更新的参数调用循环函数来更新状态。

(define (add i x l)
  ;; handle base cases outside of recursion, such as
  ;; if the starting list is empty, `i` is disregarded etc.
  (cond [(null? l) (cons x l)]
        [(null? (cdr l))
         (if (<= i 0)
             (cons x l)
             (append l (list x)))]
        [else
         (let recur ([start l] [index 0])
           ;; base case
           (if (= index i)
               (cons x start)
               ;; this is how states are updated
               (cons (car start) (recur (cdr start) (+ index 1)))))]))


;; > (add 3 'newguy '(mary peter nguyen joo kim))
;; '(mary peter nguyen newguy joo kim)
相关问题