【发布时间】:2014-02-01 22:57:41
【问题描述】:
我是 Lisp 新手,遇到了关于递归和函数返回的问题。为了更好地理解和解决我的问题,我提供了以下场景。如果它很冗长,我很抱歉。如果这会激怒其他人,我很乐意将其减少。要直接跳到业务,请从水平线开始阅读。
想象一下酒吧的女服务员。她没有接受酒水订单,而是强迫她的顾客表明自己是啤酒、朗姆酒、威士忌或这些的某种组合的饮用者。然后她拿起一个装满啤酒、朗姆酒或威士忌的托盘,绕着吧台转了一圈,只给任何自称是该特定饮料饮用者的顾客留下一杯饮料。当她完成每一轮比赛时,她总是坐下来喝一杯长岛冰茶。之后,她又拿起另一盘专门放一种饮料的托盘,再次出去送货。没有人可以拒绝喝酒,也没有人可以改变他们的饮料偏好。
现在,Mindy(女服务员)需要一种新颖的方式来跟踪她为每位顾客提供的每种类型的饮料的数量。明迪数学不是很好,到了晚上,所有的长岛冰茶真的加起来了。
所以当她要求一个简单的解决方案来跟踪她的饮料分配时,我自然建议创建一个简单的 Lisp 小程序。工作原理如下:当她送完一轮美味饮料后,Mindy 只需走到她的 Altair 8800 前并输入以下内容:
(update-orders <order-list> <drink>)
所有顾客的名单和他们的订单在哪里,是她最近一次外出时刚刚供应的饮料。
它应该正确地检查顾客名单和他们的饮料数量,将适当的饮料更新为一种,而让其他人不理会。为了与现有的计算机系统交互,完成后需要从函数中返回一个新更新的订单列表。
就在今天遇到了一个bug:正确调用函数后,返回的值不是我想要的。该列表每次仅包括列表中第一位顾客的最后一个饮料计数列表。与 Lisp 不同,递归编程是真正的罪魁祸首,我尝试修改代码来解决这个问题,但无济于事。我需要从函数返回的完整列表。
你可能已经猜到了,这个故事不是真的。我试图解决的真正问题与微积分有关,对于那些接触 Lisp 的人来说,这是一个众所周知的话题。然而,我的问题不在于我的分配,而是围绕递归调用并将完整的值列表返回给调用函数,以便我可以构建一个完整的所有术语列表,以便在完成时返回。在我能够解决这个子问题之后,我距离将它应用到我的实际任务并解决它只是一箭之遥。
运行以下函数调用:
(update-orders (quote ( (bill (4 beer) (5 whiskey)) (jim (1 beer)) (kenny (1 whiskey) (4 rum)) (abdul (1 beer) (3 whiskey) (2 rum) ))) (quote beer))
让我返回以下内容:
((5 WHISKEY))
相反,我想要一个与提供给上述函数的格式相同的列表。
请看下面的代码。为了方便起见,它已被修改为将调试输出包括到屏幕上。功能饮料清单可能是我的麻烦所在。
(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 的建议合并到我的代码中。新的 order 和 update-order 函数如下所示:
(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 WHISKEY)) ((1 BEER)) ((4 RUM)) ((2 RUM)))
这是一个嵌入列表的列表(我相信是 2 个深度),其中包括列表中每个顾客的所有最后饮品项目和饮品数量(Bill 的最终列表条目是 5 威士忌,Jim 最终条目是 1 啤酒, ETC)。他们的前 n-1 杯饮料不会添加到他们的饮料返回列表中。
我是否误读了您的建议?我有一种感觉,我离这里只有半步之遥。
【问题讨论】:
-
“
(update-orders (order-list drink))其中order-list是所有客户及其订单的列表,而“drink”是她最近一次外出时刚刚提供的饮料。“如果order-list是一个列表,你的意思应该是(update-orders order-list drink),对吧? -
我当然做到了,先生。我会修改。我注意到在 Lisp 中这样做的极端倾向。也许是我的 Java 背景?也感谢您的其他收获。