在Scheme中向List添加元素

nam*_*ked 8 scheme list racket

下面是我的代码,它将列表的car元素(carVal)和列表(初始化为空)作为参数.我想将元素追加到列表中,但同样不起作用.

(define populateValues
   (lambda (carVal currVal)
      (append currVal(list carVal ))
       (display currVal)))
Run Code Online (Sandbox Code Playgroud)

显示屏始终显示空列表().谁能帮我理解为什么?

Zor*_*orf 25

好吧,有append!一个原始的,它解决了你的大多数问题,正如已经指出的,Scheme倾向于对变异皱眉,它是可能的,但通常是避免的,所以变异的所有程序!在它们的末尾都有一个(称为爆炸).

此外,set!不改变数据,它改变一个环境,它使变量指向另一个东西,原始数据保持不变.

Scheme中的变异数据非常繁琐,但是,给你我自己的追加实现!看看它是如何完成的:

(define (append! lst . lsts)
  (if (not (null? lsts))
      (if (null? (cdr lst))
          (begin
            (set-cdr! lst (car lsts))
            (apply append! (car lsts) (cdr lsts)))

          (apply append! (cdr lst) lsts))))
Run Code Online (Sandbox Code Playgroud)

注意使用set-cdr!,这是一个真正的mutator,它只适用于对,它会改变内存中的数据,不像`set!'.如果一对传递给一个函数并用set-cdr进行变异!或者set-car !,它会在程序中的每个位置发生变异.

这服从SRFI追加!例如,声明它应该是可变参数并且应该返回未定义的值.

(define l1 (list 1 2 3 4))

(define l2 (list 2 3 4))

(define l3 (list 3 1))

(append! l1 l2 l3)

l1

l2

l3
Run Code Online (Sandbox Code Playgroud)

哪个显示:

(1 2 3 4 2 3 4 3 1)
(2 3 4 3 1)
(3 1)
Run Code Online (Sandbox Code Playgroud)

如可见,追加!可以采用无数个参数,除了最后一个,它都会变异.

虽然Scheme可能不是你理想的语言.使用追加!如前所述是非标准的,相反,append是首选的,它不会发生变异并被称为其返回值.我这样实现的:

(define (append . lsts)
  (cond
    ((null? lsts) '())
    ((null? (car lsts)) (apply append (cdr lsts)))
    (else (cons (caar lsts) (apply append (cdar lsts) (cdr lsts))))))


> (append (list 1 2 3) (list 4 5 6) (list 'granny 'porn))
(1 2 3 4 5 6 granny porn)
Run Code Online (Sandbox Code Playgroud)

在没有突变,大量使用递归和不使用测序的情况下,这显示了更熟悉的Scheme样式.

编辑:如果您只想将一些元素添加到列表中而不是本身加入两个:

(define (extend l . xs)
  (if (null? l) 
      xs
      (cons (car l) (apply extend (cdr l) xs))))

(define (extend! l . xs)
  (if (null? (cdr l))
      (set-cdr! l xs)
      (apply extend! (cdr l) xs)))

(extend '(0 1 2 3) 4 5 6)

(define list1 '(0 1 2 3))

(extend! list1 4 5 6)

list1
Run Code Online (Sandbox Code Playgroud)

这符合您的期望

  • @ darkie15并不能使答案变得“有用”或“清晰”,如果人们因为这些原因而对它不满意,那么该站点已经丢失。此外,您还是有答案的。=)此外,其他人可以根据需要进行编辑。 (2认同)

Eli*_*lay 5

  1. append创建一个列表,它不会修改现有列表.
  2. 这是因为一般来说,Scheme(和本案例中的Racket)是一种更喜欢功能风格的语言.
  3. 你可以稍微接近一点set!- 但即使这样也会让你失望,因为它只会修改本地绑定.
  4. 请注意,特别是在Racket中,列表是不可变的,因此没有什么可以更改列表.
  5. 此外,即使您可以通过这种方式修改列表,这也是一种非常低效的累积长列表的方法,因为您必须重复扫描整个列表.
  6. 最后,如果您在此级别遇到问题,那么我强烈建议您查看HtDP