简体   繁体   English

列表递归在附加时返回空列表

[英]recursion over lists return empty list while appending

I am writing a program in Scheme that receives one list with numbers and two empty lists. 我正在Scheme中编写一个程序,该程序接收一个带有数字的列表和两个空列表。 I would like that the positive numbers are joined to one list, while the negative numbers are put in another list. 我希望将正数加入一个列表,而将负数放入另一个列表。 At the end I would like to return the join of both lists. 最后,我想返回两个列表的联接。 I am using for this purpose append like this: 我为此目的使用追加:

(define (joinLists listInic list1 list2)
  (if (empty? listInic)
      (append list1 list2)
      (begin
        (if (> (car listInic) 0)
            (append list1 (car listInic))
            (append list2 (car listInic))
            )
        (joinLists (cdr listInic) list1 list2))))

but when I run it with some data like: 但是当我用一些数据运行它时:

(joinLists '(4 5 -5 -4) '() '()) (joinLists'(4 5 -5 -4)'()'())

it always returns the empty list () 它总是返回空列表()

what am I doing wrong? 我究竟做错了什么?

append does not change the value of the list, it produces a new list with the given item appended. append不会更改列表的值,它会生成一个附加了给定项目的新列表。 Since you don't actually use the value produced by append , your use of append has no effect at all. 由于您实际上并未使用append产生的值,因此您对append的使用完全无效。 As a general rule of thumb using begin only makes sense when the functions you're calling in it have side-effects, which append does not. 由于使用一般的经验法则begin才有意义,当你调用它有副作用的功能的, append不。

What you should do is pass the result of the append as an argument to the recursive call to joinLists . 您应该做的是将append的结果作为参数传递给对joinLists的递归调用。

The way you're using append is wrong. 您使用append是错误的。 Sure, we can write this: 当然,我们可以这样写:

(append list1 (list (car listInic))) ; second argument should be a list

… but the list1 parameter is not being modified in-place, instead a new list is created - and given that you didn't assign it or pass it around as aa parameter, then the new list is lost - that's why you're always getting an empty list as a result, the list parameters were never modified. …但是list1参数没有就地修改,而是创建了一个新列表-鉴于您没有分配它或将其作为aa参数传递,那么新列表就丢失了-这就是为什么您总是结果得到一个空列表,列表参数从未修改过。 We have to do something like this: 我们必须做这样的事情:

(define (joinLists listInic list1 list2)
  (cond ((empty? listInic)
         (list list1 list2))
        ((positive? (car listInic))
         (joinLists (cdr listInic) (cons (car listInic) list1) list2))
        (else
         (joinLists (cdr listInic) list1 (cons (car listInic) list2)))))

Some points to consider: 需要考虑的几点:

  • It's better to use cond when we have multiple conditions, instead of nesting if s and begin s 这是更好地使用cond当我们有多个条件,而不是嵌套if S和begin小号
  • Use positive? 使用positive? to test if a number is greater than zero 测试数字是否大于零
  • Pass the results around as parameters, as mentioned above, simply appending them (or consign them, or whatever) won't modify lists in-place 如上所述,将结果作为参数传递,仅将它们附加(或委托它们,或其他方式)不会就地修改列表
  • Use cons whenever possible, instead of append - it's much cheaper, because it adds elements at the head of the list, whereas append traverses the whole list and creates a new list, and besides its last argument should also be a list, for building a proper list 只要有可能,就使用cons而不是append这样做便宜得多,因为它在列表的开头添加了元素,而append遍历了整个列表并创建了一个新列表,除了它的最后一个参数还应该是一个列表,用于构建适当的清单

Regarding the last point, if you absolutely have to preserve the original order from the input list, even so it would be better to use cons and then reverse the output lists at the end - one again, avoiding append . 关于最后一点,即使您绝对必须保留输入列表中的原始顺序,即使这样,最好使用cons然后在末尾reverse输出列表,这又是一个更好的选择,避免使用append For instance, here's the output for the sample input: 例如,这是示例输入的输出:

(joinLists '(4 5 -5 -4) '() '())
=> '((5 4) (-4 -5))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM