Recursion 将递归生成的列表返回到Lisp中的调用函数时出现问题

Recursion 将递归生成的列表返回到Lisp中的调用函数时出现问题,recursion,lisp,clisp,Recursion,Lisp,Clisp,我是Lisp新手,对递归和函数返回有疑问。为了更好地理解和解决我的问题,我提供以下场景。如果是冗长的,我道歉。如果这激怒了其他人,我很乐意减少它。若要直接跳到业务,请从水平线开始阅读 想象一下酒吧里的女服务员。她强迫顾客自称是啤酒、朗姆酒、威士忌或这些饮料的混合饮料的饮用者,而不是点饮料。然后,她抓起一个装满啤酒、朗姆酒或威士忌的托盘,绕着酒吧转了一圈,只留下一杯饮料给任何一位确认自己是该饮料饮用者的顾客。每次结束后,她都会坐下来喝一杯长岛冰茶。之后,她继续抓起另一盘专门的一种饮料,再次出去送货

我是Lisp新手,对递归和函数返回有疑问。为了更好地理解和解决我的问题,我提供以下场景。如果是冗长的,我道歉。如果这激怒了其他人,我很乐意减少它。若要直接跳到业务,请从水平线开始阅读

想象一下酒吧里的女服务员。她强迫顾客自称是啤酒、朗姆酒、威士忌或这些饮料的混合饮料的饮用者,而不是点饮料。然后,她抓起一个装满啤酒、朗姆酒或威士忌的托盘,绕着酒吧转了一圈,只留下一杯饮料给任何一位确认自己是该饮料饮用者的顾客。每次结束后,她都会坐下来喝一杯长岛冰茶。之后,她继续抓起另一盘专门的一种饮料,再次出去送货。没有顾客可以拒绝一杯饮料,也没有人可以改变他们的饮料偏好

现在,Mindy(女服务员)需要一种新颖的方法来记录她为每位顾客提供的每种饮料的数量。明蒂的数学不是很好,到了晚上,所有长岛冰茶的数量都在增加

因此,当她要求一个简单的解决方案来跟踪她的饮料分配时,我自然建议创建一个简单的Lisp小程序。工作原理如下:当Mindy完成一轮美味饮料后,她只需走到她的Altair 8800并键入以下内容:

(update-orders <order-list> <drink>)
相反,我希望列表的格式与上面提供给函数的格式相同

请参阅下面的代码。为方便起见,已对其进行了修改,将调试输出包括在屏幕中。功能饮料清单可能是我的麻烦所在

(defun update-orders (x d)
    (print 'orders)
    (prin1 x)
    (order (car x) d)
)

(defun order (x d)
    (print 'order)
    (prin1 x)
    (drink-list (cdr x) d)
)

(defun drink-list (x d)
    (print 'drink-list)
    (prin1 x)
    ;(append
    ;(cons
    ;(list
        (drink-count (car x) d)
        (cond
            ((cdr x) (drink-list (cdr x) d))
            (t x)
        )
    ;)
)

(defun drink-count (x d)
    (print 'drink-count)
    (prin1 x)
    (list
        (cond
            ((eq (car (cdr x)) d)    
                (modify-count (car x) 1))
            (t x)
        )
    )
)

(defun modify-count (x d)
    (print 'modify-count)
    (prin1 x)
    (print 'new-modify-count)
    (prin1 (+ (parse-integer (subseq (write-to-string x) 0)) 1))
    (list
        (+ (parse-integer (subseq (write-to-string x) 0)) 1)
    )
)
编辑:

我已经将ooga的建议合并到我的代码中。新订单和更新订单功能如下所示:

(defun update-orders (x d)
    (cond
        ((null x) ())
        (t        (cons (order (car x) d) (update-orders (cdr x) d)))
    )
)

(defun order (x d)
    ;(print 'order)
    ;(prin1 x)
    (drink-list (cdr x) d)
)
现在返回以下列表,运行与上面相同的函数调用:

((5杯威士忌))((1杯啤酒))((4杯朗姆酒))((2杯朗姆酒)))

这是一个嵌入列表的列表(我相信有两个深度),包括列表中所有最后的饮料项目和每位顾客的饮料数量(比尔的最终列表条目是5杯威士忌,吉姆的最终条目是1杯啤酒,等等)。他们的第一批n-1饮料不会添加到他们的饮料返回列表中


我误解了你的建议吗?我有一种感觉,我离这里只有半步之遥。

在更新订单中,您只需将x的车交给订单即可。x的其余部分完全被忽略。然后,您只传递“要喝的饮料”列表上的cdr

下面是一个程序,它向给定列表的每个成员添加1,以说明代码的结构

调用示例:
(增量列表(1233))

增量列表
更改为
更新订单
,将
增量
更改为
订单
(并添加第二个输入等),我认为这应该是您的程序结构

此外,您应该尝试从下往上构建它。尝试编写一个函数,如果(数字饮料)列表中的给定饮料匹配,该函数将向数字中添加一个。即,鉴于此:

(add-one-if '(4 beer) 'beer)
它应该归还这个

(5 BEER)
(3 WHISKEY)
鉴于此

(add-one-if '(3 whiskey) 'beer)
它应该归还这个

(5 BEER)
(3 WHISKEY)

正如上面所建议的,下面是我为解决我的问题而实现的完整代码,包含了ooga提供的建议结构

;;;; WAITING-TABLES

(defun update-orders (x d)
    (cond
        ((null x) ())
        (t        (cons (order (car x) d) (update-orders (cdr x) d)))
    )
)

(defun order (x d)
    (cons (car x)  (drink-list (cdr x) d))
)

(defun drink-list (x d)
    (cond
        ((null x) ())
        (t        (cons (drink-count (car x) d) (drink-list (cdr x) d)))       
    )
)

(defun drink-count (x d)
    (cond
        ((eq (car (cdr x)) d)
            (cons (modify-count (car x) 1) (drink-count (cdr x) d)))
        (t x)
    )
)

(defun modify-count (x d)
    (+ (parse-integer (subseq (write-to-string x) 0)) 1)
)

(更新订单(订单列表饮料))
其中,
订单列表
是所有客户及其订单的列表,“饮料”是她最近一次外出时刚供应的饮料。”如果
订单列表
是一个列表,您可能指的是
(更新订单列表饮料)
,对吗?我当然这么做了,先生。我会修改。我注意到在Lisp中有这样一种极端的倾向。也许是我的Java背景?也谢谢你的其他捕获。我已经编辑了我的帖子,包括你建议的更改。进展,但不完全。也许我误解了什么。谢谢!这让我离开了屏幕几米在充分理解cons参数的工作原理后,我将您的建议纳入了另外两个函数中。这100%解决了我的问题,我终于感觉我理解了Lisp的这一方面(以及一般的编程)完全。非常感谢,先生。太好了!很高兴能提供帮助。如果您愿意,请将您的解决方案发布为“答案”(您可以发布您自己问题的答案),我会看一看。这看起来很好。我唯一能看到的(可能是我错了)是,饮料计数和修改计数可以替换为
(defun drink count(x d)(cond((eq(car(cdr x))d)(cons(+(car x)1)(cdr x)))(tx)))
谢谢。我也会在我的作业中使用这个修改,这是一个基于这个相关示例的更复杂的程序。应该也会为我节省一些不动产。干杯!