【问题标题】:Comparing a number and a list object in lisp比较lisp中的数字和列表对象
【发布时间】:2016-03-07 19:43:57
【问题描述】:

我是 lisp 新手,所以如果提前,我很抱歉这是一个简单的问题。

我有一个清单:

(set ‘inventory ‘(parts
                   ((item 1001) (shoes (color brown) (size 10) (cost 20))) 
                   ((item 2011) (skirt (color blue) (size 4) (cost 10)))
                   ((item 2120) (pants (color white) (size 32) (cost 30)))
                   ((item 2121) (pants (color brown) (size 34) (cost 30)))))

我正在尝试编写一个按项目编号查看列表并返回正确的函数。

(findItem 1001 inventory) 应该返回:

((item 1001) (shoes (color brown) (size 10) (cost 20)))

这是我目前所拥有的:

(defun findItem (q i)   
    (cond
        ((null q)
         nil)
        ((null (cdr i))
         nil)
        ((eq `parts (car i))
         (findItem q (cdr i)))
        ((eq q (cdr (car (car i))))
         (car i))
        (T
         (findItem q (cdr i)))))

除了((eq q (cdr (car (car i)))) (car i)) 之外似乎一切正常

(cdr (car (car i))) 应该返回 (1001) 或部件号

但 eq 的计算结果不为 true,因此函数整体返回 nil。

我们将不胜感激

【问题讨论】:

标签: lisp


【解决方案1】:

What's the difference between eq, eql, equal, and equalp in Common Lisp? 中所述,使用 eq 比较 cons 单元格是错误的。 您应该使用equal 或提取 数字,即将(cdr (car (car i))) 替换为 cadaar 这样 你会得到1001 而不是(1001)

另外,set 已弃用,请使用 setqdefparameter 代替。

另外,您可以使用内置 find 改为:

(find 1001 (cdr inventory) :key #'cadar)
==> ((ITEM 1001) (SHOES (COLOR BROWN) (SIZE 10) (COST 20)))

【讨论】:

    【解决方案2】:
    (cdr (car (car '((item 1001) (shoes (color brown) (size 10) (cost 20))))))
    

    不起作用,因为 caaritem 并且您不能使用符号的 cdr。 在你做对之前,你应该像这样玩它:

    (defparameter *item*  '((item 1001) (shoes (color brown) (size 10) (cost 20))))
    (car *item*) ; ==> (item 1001)
    (caar *item*) ; ==> item
    (cdar *item*) ; ==> (1001)
    

    现在c<runs of a and d>r 是嵌套carcdr 的缩写,例如(car (cdr (cdr x)))(也称为third)可以缩写为caddr,当从右到左阅读as 和ds 时,你明白为什么.

    数字不保证是eq,即使它们代表相同的值。当两个值看起来相似并且 = 仅适用于在某些实现中可能更快的数字时,Tou 可以使用 equal 来获取真值。

    set 已弃用。要制作全局变量,请使用defparameter 并使用*earmuffs* 表示它们是全局变量。

    我敦促您选择合理的名称,例如 qi 并没有任何意义。还使用CL coding conversion 使您的代码简洁明了,其他lisper 也可以阅读。例如:

    (defun find-item (item-number inventory)
      "Finds the record in inventory that has a specific item number"
      (cond ((endp inventory) nil)
            ...))
    

    【讨论】:

      【解决方案3】:

      为了扩展sds's answer,让我解决一些风格问题。与任何其他语言一样,您应该尝试设计代码以定义合理的界面。

      我可以告诉你,你可能更喜欢使用结构或对象,但我实际上认为使用列表并不一定是坏事。困扰我的是CADARCDR 的显式使用:您正在对您的代码做出假设,这会无缘无故地引入耦合。将抽象与实现分离的第一步是定义访问器函数,例如item-referencerow-reference(针对每个条目)等等。

      如果您碰巧重新组织数据,您会很高兴知道您只需将定义(item-reference x) 的地方更改为(CAADDR x)(例如)。

      顺便说一句,如果您同时提供 :named:type list 参数,Common Lisp structures 可以在列表之上实现。例如,您可以定义一个item 结构如下:

      > (defstruct (item (:type list) :named) reference)
      

      然后,下面实际上构建了一个列表,其中第一个元素指示类型:

      > (make-item :reference 300)
      => (ITEM 300)
      

      defstruct 也创建访问器:

      > (item-reference *)
      300
      
      > (setf (item-reference **) 1010)
      1010
      

      【讨论】:

        【解决方案4】:

        你有一个alist。您应该利用 built in 的现有函数来处理此数据结构。

        (defun find-item (num list)
          (assoc num (cdr list) 
                 :test (lambda (num b)
                         (equal num (second b)))))
        

        请注意,我还更改了您的函数名称以更符合列表样式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-24
          • 1970-01-01
          • 1970-01-01
          • 2011-08-08
          • 1970-01-01
          • 2015-04-02
          • 2019-01-03
          • 1970-01-01
          相关资源
          最近更新 更多