我是Lisp的新手,并且在递归和函数返回方面存在问题。为了更好地理解和解决我的问题,我提供了以下方案。如果它是冗长的,我道歉。如果这加剧了其他人,我很乐意将其削减。要想直接开展业务,请从水平线向前阅读。
想象一下酒吧里的女服务员。她没有接受饮料订单,而是强迫她的顾客认定自己是啤酒,朗姆酒,威士忌或其中某些组合的饮用者。然后,她抓起一个装满啤酒,朗姆酒或威士忌的托盘,在酒吧周围做一圈,给任何已经确定自己是特定饮料饮用者的顾客留下一杯饮料。当她完成每一轮比赛时,她总是坐下来享用长岛冰茶。之后,她继续抓住另一个专门提供一种饮料的托盘,然后再次出去送货。没有顾客可以拒绝喝酒,没有人可以改变他们的饮料偏好。
现在,Mindy(女服务员)需要一种新颖的方式来记录她为每个顾客提供的每种类型的饮料量。 Mindy并不擅长数学,到了晚上,所有长岛冰茶都真的在加起来。
因此,当她要求一个简单的解决方案来跟踪她的饮料配方时,我自然建议创建一个简单的小Lisp程序。以下是它的工作方式:当她完成提供一系列美味饮料后,Mindy只需走到她的Altair 8800并输入以下内容:
(update-orders <order-list> <drink>)
所有顾客及其订单的清单在哪里,是她最近一次出去喝的饮料。
应该正确浏览顾客名单和他们的饮料数量,更新适当的饮料,然后单独留下。要与适当的计算机系统连接,需要在函数完成时从函数返回新更新的订单列表。
就在今天,我遇到了以下错误:正确调用该函数后,返回的值不是我想要的。该列表仅包括列表中第一个客户的最后一个饮料计数列表。递归编程是真正的罪魁祸首,而不是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的建议纳入我的代码中。新订单和更新订单功能如下所示:
(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个深度,包括列表中每个顾客的所有最后饮品和饮料数量)(比尔的最终列表条目是5威士忌,Jim最后一个条目是1啤酒等)。他们的第一份n-1饮料不会添加到退回的饮料清单中。
我误解了你的建议吗?我感觉我离这里只有一步之遥。
答案 0 :(得分:1)
在更新订单中,您只需将x的汽车传递给订单。 x的其余部分完全被忽略。然后你只把它的cdr传递给drink-list。
作为如何构建代码的示例,这是一个为给定列表的每个成员添加1的程序。
示例电话:(increment-list '(1 2 3))
(defun increment-list (x)
(cond
((null x) ())
(t (cons (increment (car x)) (increment-list (cdr x))))
)
)
(defun increment (x)
(+ x 1)
)
将increment-list
更改为update-orders
,将increment
更改为orders
(并添加第二项输入等),我认为应该是您的计划结构。< / p>
此外,您应该尝试从下往上构建它。尝试编写一个函数,如果(数字饮料)列表中的给定饮料匹配,该函数将为该数字添加一个。即,鉴于此:
(add-one-if '(4 beer) 'beer)
它应该返回
(5 BEER)
鉴于此
(add-one-if '(3 whiskey) 'beer)
它应该返回
(3 WHISKEY)
答案 1 :(得分:0)
如上所述,这里是我为解决我的问题而实现的完整代码,其中包含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)
)