【问题标题】:Searching for a integer in a list (Lisp)在列表中搜索整数 (Lisp)
【发布时间】:2013-09-22 00:46:02
【问题描述】:

我想不出一种方法来搜索列表以确保它包含所有整数。如果有非整数数据,我想立即返回nil,如果没有,则继续我的功能。

我试图创建的递归函数将conscar 与列表的cdr。通过我所做的尝试,我无法返回nil。我只能忽略非整数数据。例如,(add-1-all '(1 2 3 a)) 将在每个数字加一后返回 (2 3 4)

    (defun add-1-all (L) 
            (if (null L) 
                L
              (if (integerp (car L))
                  (cons (+ (car L) 1) (add-1-all (cdr L)))
                  nil)))

我确实知道这样做是有缺点的,因为递归正在添加到列表中。

【问题讨论】:

    标签: lisp common-lisp


    【解决方案1】:

    你的第一句话,

    我想不出在 Lisp 中搜索列表以确保它包含所有整数的方法。

    听起来你想检查一个列表是否全是整数。您可以使用every检查列表是否全是整数:

    CL-USER> (every 'integerp '(1 2 3 4))
    ;=> T
    CL-USER> (every 'integerp '(1 2 a 4))
    ;=> NIL
    

    every 将处理短路,即,一旦发现第一个不符合谓词的元素,就会返回 nil

    但是,您的代码听起来像是要在列表上进行映射,收集应用于每个整数的函数的值并返回收集的值,但如果遇到非整数,则返回 null。也许最简单的方法是使用loop 宏。一个解决方案看起来几乎与英文规范相同:

    CL-USER> (loop for x in '(1 2 3 4)
                if (not (integerp x)) return nil
                else collect (1+ x))
    
    ;=> (2 3 4 5)
    CL-USER> (loop for x in '(1 2 a 4)
                if (not (integerp x)) return nil
                else collect (1+ x))
    
    ;=> NIL
    

    使用loop 执行此操作也比递归解决方案具有一些优势。虽然 Lisp 家族中的某些语言(例如 Schema)需要尾调用优化,并且一些 Common Lisp 实现也这样做,但 Common Lisp 中不需要。因此,如果您使用迭代解决方案(例如,使用loop)而不是递归(甚至是尾递归)实现,它会更安全(例如,您不会耗尽堆栈空间)。

    【讨论】:

      【解决方案2】:

      关键是使用辅助函数,并且该辅助函数在递归时将答案与它一起携带,以便它可以在必要时随时丢弃整个事物。顺便说一句,这也是tail recursive,这意味着它可以处理极长的列表而不会耗尽堆栈空间。

      (defun add-1-all (L) 
        (add-1-all-helper L nil))
      
      (defun add-1-all-helper (L answer)
        (if (null L)
          answer
          (if (integerp (car L))
            (add-1-all-helper
              (cdr L)
              (cons (+ (car L) 1) answer)))))
      

      【讨论】:

      • 这是有道理的。如果没有辅助函数,有没有办法做到这一点?
      • 你可以编写一个函数,它接受可变数量的参数,如果它有 1 个参数,则其行为类似于 add-1-all,如果它有 2 个,则其行为类似于 add-1-all-helper。或者你可以将 add-1-all-helper 写在letadd-1-all 内,如果您只是担心会污染您的命名空间。
      • @NeilForrester 你忘了反转答案。此外,您可以通过使用带有默认值或标签的可选参数来不使用辅助函数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      • 2019-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多