无法将递归构建的列表返回给Lisp中的调用函数

时间:2014-02-01 22:57:41

标签: recursion lisp clisp

我是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饮料不会添加到退回的饮料清单中。

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

2 个答案:

答案 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)
)