使用lisp中的子列表和原子反转列表

时间:2016-04-28 23:40:20

标签: scheme lisp

我是函数式编程的新手,并尝试在lisp中反转列表。列表由子列表和原子组成。函数(reverse-tree '((1 2) 5 6 (3)))应返回((3) 6 5 (2 1))。这是我的功能:

(define (reverse-tree s)
    ;; giving problem with an atom 
  (if (not(list? s)) ( reverse-tree s) (reverse (map reverse s)))

  )

当我(reverse-tree '((1 2) (3))) =>时,它会起作用((3) (2 1))。但是当我(reverse-tree '((1 2) 5 6 (3)))时它会崩溃。我得到的错误是reverse: contract violation expected: list?

我仅限使用reverse, map, if, cond, list? null?个功能。

编辑,有人将此问题标记为重复,但此问题存在限制,这与其他问题不相似。我无法使用 conscarcdrappend。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

考虑问题。首先,如果函数被赋予列表作为参数,则需要反转该列表。这很容易,比如:

(define (reverse-tree tree)
  (if (list? tree)
      (reverse tree)
      ...))

但是您还需要反转其中的所有子列表以及其中的所有子列表,依此类推。由于这正是我们的reverse-tree所做的,我们应该使用map将其应用于反向列表中的所有元素(在反转之前或之后使用map实际上并不重要列表):

(define (reverse-tree tree)
  (if (list? tree)
      (map reverse-tree (reverse tree))
      ...))

但如果输入为((1 2) 3 4 (5 6)),则map也会在原子reverse-tree3上调用4。反转它们没有任何意义,所以我们可以回复它们:

(define (reverse-tree tree)
  (if (list? tree) 
      (map reverse-tree (reverse tree))
      tree))

现在应该有效:

(reverse-tree '((1 2) 3 4 (5 6)))
;=> ((6 5) 4 3 (2 1))
(reverse-tree '((1 2) 3 4 (5 6 (7 8))))
;=> (((8 7) 6 5) 4 3 (2 1))