在Scheme中创建非常大的列表

在Scheme中创建非常大的列表,scheme,Scheme,我随身携带物品清单。这些对象称为字对 例如:((WordPair1)(WordPair2))等等。我有一个函数提取它们的置信值。我想用它们的置信值创建另一个列表。该列表将只有数字。在这个计算结束时,我将得到一个与单词对列表相对应的数字列表。我知道如何使用cons创建基本列表。这里的问题是,我有500000个字对,使用递归cons,我会很快遇到堆栈溢出 解决办法是什么 我天真的解决方案是: (define (create-conf-list lst) (define wp (car lst)) (

我随身携带物品清单。这些对象称为字对

例如:
((WordPair1)(WordPair2))
等等。我有一个函数提取它们的置信值。我想用它们的置信值创建另一个列表。该列表将只有数字。在这个计算结束时,我将得到一个与单词对列表相对应的数字列表。我知道如何使用
cons
创建基本列表。这里的问题是,我有500000个字对,使用递归cons,我会很快遇到堆栈溢出

解决办法是什么

我天真的解决方案是:

(define (create-conf-list lst)
(define wp (car lst))
(define confidence (tv-conf (cog-tv wp)))
(if (not (null? (cdr lst)))
    (cons confidence (create-conf-list (cdr lst)))
    '()))
如何改进这一点


附言:我用这种方法遇到了堆栈溢出。我需要一个更有效的方法。我想不出如何在这里插入尾部递归。

这看起来像是你可以用“累加和反转”来做的,因为你希望结果与直接累加产生的结果相反:

  (define (helper ls acc)
    (define wp (car ls))
    (define confidence (tv-conf (cog-tv wp)))
    (if (null? (cdr ls))
        (reverse acc)
      (helper (cdr ls) (cons confidence acc))))
这是尾部递归,因为递归案例只是对函数本身的调用-递归调用的结果不用于任何其他内容。
需要反转,因为累加器中的
cons
以相反的顺序构建列表。
(您可能会尝试使用
(append acc(list confidence))
将列表保持在所需的顺序,但是
append
使其速度非常慢。)

然后您可以从“实际”函数调用它:

(define (create-conf-list lst)
  (helper lst '()))
或者,您可以将这些函数合并为一个:

(define (create-conf-list lst)
  (define (helper ls acc)
    (define wp (car ls))
    (define confidence (tv-conf (cog-tv wp)))
    (if (null? (cdr ls))
        (reverse acc)
      (helper (cdr ls) (cons confidence acc))))
  (helper lst '()))
旁注:
你放弃了自信的最后一个要素,但由于你正处于优化阶段,我想这就是你想要的。

如果它不是您想要的,您应该在考虑优化之前修复该错误。

通过函数将列表映射到相应的值列表通常使用map完成

(define (get-confidence-values list-of-word-pairs)
  (map (lambda (wp) (tv-conf (cog-tv wp)))
       list-of-word-pairs))

很抱歉我的意思是检查列表是否为null,而不是
(cdrlst)
,这尾递归是如何实现的?你能解释一下密码吗?我想不出这里面的尾部递归,明白了!非常感谢。积累到底是什么?“你能给我指出一些解释累加的资源吗?”RohitShinde在讨论尾部递归时,有任何关于函数编程的书,特别是Scheme。如果你有“SICP”——计算机程序的结构和解释()——请阅读有关迭代过程的章节。如何设计程序(“HtDP”)也很重要。似乎表明您的方法更快(可能是因为
map
是内置的)。@WillNess 500000个实体如果堆栈帧较大,可能会导致堆栈分配问题。另一方面,如果每个对象的大小为1000字节,那么仍然只有半GB的分配空间(或者少于1.00美元的RAM)<代码>映射是这样一种地方,在这种地方,为了实现而下拉到C中,为了性能而在内部使用变异可能是合理的。@这就是为什么使用
映射
是“通常完成的”。关于“大”的另一个问题只是需要时间来了解它对算法效率的依赖性。如果算法有O(30!),那么30是很多,而现在如果算法是O(n),那么200万算不了什么,就像处理列表操作时一样。为了方便起见,可以使用结构变异以自顶向下的方式迭代构建列表。