列出Scheme中的遍历

时间:2014-09-24 17:35:58

标签: scheme racket

myList是一个列表,其元素既可以是myList的相同类型的符号或列表。 例如:myList ='(a b(a d c)d())等等

我想在Scheme中编写一个只会遍历它的函数(最终我将用其他值替换符号)。

我写了这个函数:

(define traversal (lambda (myList)
       (if (null? myList) '()
           (if (and (list? (car myList)) (not (null? (car myList))))
               (list (traversal (car myList)) (traversal (cdr myList)))
               ; else if car is an empty list
               (if (null?  (car myList))
                   (list (traversal (cdr myList)))
                   ; else car is a symbol
                   (append (list (car myList)) (traversal (cdr myList))))))))

它为myList的某些配置提供了正确的结果,但绝对不是那个。 例如,

(display (traversal '((f) h (r t b) (x m b m y) b (c (d))))) 

增加了我不需要的附加功能。

显示此类列表的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

您接近解决方案。以下是一些提示:

而不是嵌套if尝试使用cond表单,它更具可读性。

表达式(and (list? (car myList)) (not (null? (car myList))))是正确的,但您可以使用更短的(pair? (car myList))并执行几乎相同的操作。

traversal应返回一个列表,但在此处使用带有列表参数的list (list (traversal (car myList)) (traversal (cdr myList))) 将返回列表列表。例如。 (list '(a) '(b))将返回((a) (b))而不是(a b)。在这些情况下,您应该使用append (append '(a) '(b)) - > (a b)

如果值不是列表但您想将其添加到现有列表,请使用cons过程。 (cons 'a '(b c)) - > (a b c)

答案 1 :(得分:1)

  1. 您在很多地方测试null?,其中一次测试通常就足够了。
  2. 您很少在这些遍历中使用list,而只是cons
  3. 此外,最好避免append,此处不需要。{/ li>
  4. 使用(car ...)表单优化let的重复使用。
  5. 代码的简化形式为:

    (define traversal 
      (lambda (myList)
        (if (null? myList) 
            '()
            (let ((c (car myList)))
              (cons (if (list? c) (traversal c) c)
                    (traversal (cdr myList)))))))
    

    修改

    虽然此过程适用于正确的列表,但它不适用于不正确的列表(尽管看起来如此)。以下是一种更通用的方法,适用于各种S-expression,包括正确的列表,我建议使用以上代码:

    (define traversal
      (lambda (sexp)
        (cond
          ((null? sexp) '())
          ((pair? sexp) (cons (traversal (car sexp))
                              (traversal (cdr sexp))))
          (else          sexp))))