【问题标题】:Scheme- Append isn't working the wayScheme-Append 无法正常工作
【发布时间】:2015-03-23 05:00:52
【问题描述】:

我无法让它正常工作。它应该采用两个可能不同长度的列表,并将元素一起添加到一个列表中。

例如,(polyAdd '(1 2 3 4) '(1 2 3)) 将产生 (2 4 6 4)。

这是我现在的程序。我认为它应该可以工作,但它只是打印出来(2 4 6),我不明白。

这是程序:

(define (polyAdd l ll)
  (let ((num (- (length l) (length ll))))
    (if (> num 0)
        (append ll (nzero num))
        (append l (nzero (- 0 num)))))
  (if (not (or (= (length l) 1) (= (length ll) 1)))
      (cons (+ (car l) (car ll)) (polyAdd (cdr l) (cdr ll)))
      (cons (+ (car l) (car ll)) '())))

(define (nzero n)
  (if (= n 0)
      '()
      (cons 0 (nzero (- n 1)))))

感谢 Sylwester,我只需在附加前添加 (set! ll 即可使其正常工作。

【问题讨论】:

  • 从未使用过append 的结果。它不会改变任何值。

标签: list scheme append


【解决方案1】:

使用辅助函数来处理两个多项式长度相同的情况。

(define (poly-add/same-length xs ys)
  (if (null? xs) 
      '()
      (cons (+ (car xs) (car ys)) 
            (poly-add/same-length (cdr xs) (cdr ys)))))

(define (poly-add xs ys)
  (let ((num (- (length xs) (length ys))))
    (if (> num 0)
        (poly-add/same-length xs (append ys (nzero num)))
        (poly-add/same-length (append xs (nzero (- 0 num))) ys))))

(define (nzero n)
  (if (= n 0)
      '()
      (cons 0 (nzero (- n 1)))))

(poly-add '(1 2 3 4) '(1 2 3))

【讨论】:

    【解决方案2】:

    对于二进制情况

    这听起来像是二进制 ma​​p 的变体,它不需要列表长度相等,而是在一个列表为空时使用另一个列表作为终止符。以这种方式来看,实际上根本不需要使用 append ;如果 list2 为空(反之亦然),则返回 list1

    (define (map2 f list1 list2)
      (cond
        ((null? list1) list2)
        ((null? list2) list1)
        (else (cons (f (car list1) (car list2))
                    (map2 f (cdr list1) (cdr list2))))))
    

    那么你的多项式加法函数就变成了使用 +ma​​p2 的调用:

    (map2 + '(0 1 2) '(3 4 5 8))
    ;=> (3 5 7 8)
    

    (define (add-polynomials p1 p2)
      (map2 + p1 p2))
    
    (add-polynomials '(1 2 3 4) '(1 2 3))
    ;=> (2 3 6 4)
    

    对于更一般的情况

    现在,Scheme 中的 + 函数实际上可以处理任意数量的值。使多项式加法函数以相同的方式运行可能会很好。这样做的一种方法是继续使用非空列表来为函数生成一个 arglist。

    (define (remove x lst)
      (cond 
        ((null? lst) '())
        ((eqv? x (car lst)) (remove x (cdr lst)))
        (else (cons (car lst) (remove x (cdr lst))))))
    
    (define (map-varargs f list1 . more-lists)
      (let ((all-lists (remove '() (cons list1 more-lists))))
        (if (null? all-lists)
            '()
            (cons (apply f (map car all-lists))
                  (apply map-varargs f (map cdr all-lists))))))
    

    (map-varargs + '(0 1)
                   '(2 3 4)
                   '(5 6 7 8)))
    ;=> (7 10 11 8)
    

    另一种可能的方法(对于被映射的函数不能接受可变数量的参数的情况)是实现一个在其中一个列表为空时使用一些默认值的方法。

    备注

    注意使用 null? 来检查列表是否为空。在检查 0 列表的长度是否语义等效时,检查 null 只需要一次比较,而计算列表的长度需要遍历整个列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 2016-12-01
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      • 2016-09-01
      相关资源
      最近更新 更多