【问题标题】:Scheme appending to a list without append?方案附加到列表而不附加?
【发布时间】:2021-09-18 18:20:24
【问题描述】:

我一直在尝试在不使用附加运算符的情况下将 s 表达式附加到方案中的列表。到目前为止,我已经尝试使用一个名为“next-member”的辅助函数,它将迭代到列表的下一项。这可能是一个基本的递归问题,我无法理解它,因为我是 Scheme 语法的新手:

(define next-member
  (lambda lst
    (cond
      ((not (null? lst)) (car lst))
      (else (next-member (cdr lst)))
      )))

(define append-item
  (lambda (a b)
    (cond
      ((null? b) (list a))
      ((null? a) b)
      (else (list (car b) (next-member (cdr b)) a))
      )))

【问题讨论】:

    标签: scheme racket


    【解决方案1】:

    您不需要任何辅助函数 - 您需要了解函数 cons 以及它如何用于创建列表。

    函数cons 调用从两个参数创建一个点对:

    > (cons 1 2)
    '(1 . 2)
    

    第二个参数可以是列表,然后返回第一个参数作为该列表的第一个元素的新列表:

    > (cons 1 '())
    '(1)
    > '(1 . ())
    '(1)
    > (cons 1 '(2 3))
    '(1 2 3)
    > '(1 . (2 3))
    '(1 2 3)
    

    列表构建为cons 调用链,其中最后一对的最后一个元素是空列表:

    > (cons 1 (cons 2 (cons 3 '())))
    '(1 2 3)
    > '(1 . (2 . (3 . ())))
    '(1 2 3)
    

    所以,想象一下这个任务的解决方案:

    1. 如果第一个参数为空,则返回第二个参数。
    2. 如果第二个参数为空,则返回第一个参数。
    3. 否则,使用第一个列表中的元素递归构建点对链,当您到达末尾时,将第二个列表放在末尾。像这样:
    > (cons 1 (cons 2 (cons 3 '(4 5 6))))
    '(1 2 3 4 5 6)
    

    整体解决方案:

    (define (append-list lst1 lst2)
      (cond ((null? lst1) lst2)
            ((null? lst2) lst1)
            (else (cons (car lst1)
                        (append-list (cdr lst1) lst2)))))
    

    例子:

    > (append-list '() '(1 2 3))
    '(1 2 3)
    > (append-list '(1 2 3) '())
    '(1 2 3)
    > (append-list '(1 2 3) '(4 5 6))
    '(1 2 3 4 5 6)
    

    【讨论】:

      【解决方案2】:

      另一种方法是使用突变定义附加(append! 有时或有时称为nconc)。这个想法是改变最后一个列表元素的cdr,使其指向第二个列表,而不是指向'()。

      其他方式是use folding。

      【讨论】:

        【解决方案3】:

        问题不是语法,而是语义。

        您的第一个函数说“非空列表的‘下一个元素’是它的头部;空列表的‘下一个元素’是它的尾部的‘下一个元素’”。
        这没有意义——一个空列表没有尾巴(不清楚你期望这个函数完成什么)。

        您的第二个函数说“为了将a 附加到b,创建一个包含三个元素的列表:b 的第一个元素、(cdr b) 的'下一个元素'和a” .

        看起来您实际上想要做的是在列表末尾添加一个元素。

        您可以使用最基本的列表递归“模式”来做到这一点:

        • 如果列表为空,请执行操作
        • 否则,做一些涉及列表头部和尾部递归结果的事情。

        在您的问题中,基本情况很简单;它是a 的单例列表:

        (define (append-item a bs)
            (if (null? bs)
                (list a)
        

        为了递归,你意识到你可以通过将元素最后附加到bs的尾部,然后将bs的第一个元素添加到前面来实现目标:

                (cons (car bs) (append-item a (cdr bs)))))
        

        作为旁注,这个函数的传统名称是snoc,它是“cons”倒过来。
        (另一方面,“s 表达式”是源代码;您不能将其附加到任何内容。)

        【讨论】:

          【解决方案4】:

          Append 不是原始的; cons 是。您可以使用cons 轻松创建append。这是两个参数版本的直接实现:

          (define (my-append a b)
            (if (null? a)
                b
                (cons (car a) 
                      (my-append (cdr a) b))))
          

          list 以及其他参数也在后台使用cons。如果是对,则它们是使用 cons 创建的,仅此而已!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-11-29
            • 1970-01-01
            • 1970-01-01
            • 2012-12-20
            • 1970-01-01
            • 2017-12-19
            • 1970-01-01
            相关资源
            最近更新 更多