在LispWorks中进行编程21:食谱

  • 0

在LispWorks中进行编程21:食谱

Category:UI界面编写 Tags : 

食谱

曾经看过厨房橱柜,想知道你可以做什么晚餐?然后这个程序就是答案。您首先选择您可用的成分:

然后它会告诉您可以制作的食谱:

您可以向数据库添加新配方,并更新配料列表。

完整列表

此隐藏内容查看价格为3雪花,请先

描述

配方程序使用两个全局变量。第一个,成分数据库,包含我们将要使用的所有成分的列表:

(defparameter ingredient-database ‘(“eggs” “flour” “butter” “chicken” “beef” “pork” “lamb” “sugar” “chocolate” “onions” “fish” “tomatoes” “pasta” “chorizo” “rice” “potatoes” “cheese”))

第二个是recipe-database,它将包含一个食谱列表。每个食谱都是三个项目的列表:

  • 食谱的名称。
  • 成分列表。
  • 该方法的简短描述。

因此,在添加了几个配方之后,recipe-database可能如下所示:

((“Cheese omelette” (“eggs” “cheese”)  “Beat the eggs, cook, and add the cheese”) (“Pizza” (“flour” “tomatoes” “chorizo” “cheese”)  “Make a dough, add tomato, cheese, and chorizo, and bake for 12m at 210°C”))

基本惯例

我们的出发点是程序包含测试成分是否包含在成分列表。我们将这样使用它:

CL-USER > (contains “chicken” ‘(“pork” “chicken” “rice”))T

但:

CL-USER > (contains “chicken” ‘(“pork” “chocolate” “rice”))NIL

英文定义如下:

要查看成分是否在成分列表中:

  • 如果列表为空,则答案为否。
  • 如果该成分是列表中的第一项,那么答案是肯定的。
  • 否则它就是问题的答案 – 除了第一个元素之外,其余成分中的成分是什么?

这是Lisp过程的定义:

(defun contains (item list)  (if (null list) nil    (if (string= item (first list)) t      (contains item (rest list)))))

基于此,我们定义了一个过程子集,用于检查成分列表lista是否是列表listb的子集。我们将使用如下:

CL-USER > (subset ‘(“pork” “rice”) ‘(“pork” “eggs” “rice”))T

但:

CL-USER > (subset ‘(“pork” “eggs” “rice”) ‘(“pork” “rice”))NIL

在英语中,这定义如下:

检查lista是否是listb的子集

  • 如果lista为空,那么答案是肯定的。
  • 如果listb不包含lista的第一个元素,那么答案是否定的
  • 否则它就是问题的答案 – lista的其余部分排除第一个元素是listb的一个子集吗?

作为Lisp程序,它变成:

(defun subset (lista listb)  (if (null lista) t    (if (null (contains (first lista) listb))        nil      (subset (rest lista) listb))))

食谱计划

现在我们将定义一个程序,找到您可以使用一组特定成分制作的所有食谱。我们将这样称呼它:

CL-USER > (recipes-can-make ‘(“cheese” “eggs”) recipe-database)((“Cheese omelette” (“eggs” “cheese”) “Beat the eggs, cook, and add the cheese”))

英文定义是:

要找到您可以使用配料制作的食谱:

  • 如果食谱列表为空,则回答无。
  • 如果第一个配方的成分是可用成分列表的子集,则返回该配方以及检查剩余配方的结果。
  • 否则只返回检查剩余配方的结果。

这是Lisp中的过程:

(defun recipes-can-make (ingredients recipes)  (if (null recipes) nil    (let* ((entry (first recipes))           (needs (second entry)))      (if (subset needs ingredients)          (cons entry (recipes-can-make ingredients (rest recipes)))        (recipes-can-make ingredients (rest recipes))))))

用户界面

最后,我们添加一些对话框,以便更容易地添加和查找食谱。这是添加配方的过程:

(defun add-recipe ()  (let ((name (capi:prompt-for-string “What’s the recipe?”))        (ingredients (capi:prompt-for-items-from-list                      ingredient-database                      “What does it need?”))        (method (capi:prompt-for-string “Brief method:”)))    (setq recipe-database (cons (list name ingredients method) recipe-database))))

现在这里是查找食谱的界面:

(defun find-recipe ()  (let ((ingredients (capi:prompt-for-items-from-list                      (sort ingredient-database #’string<)                      “What ingredients do you have?”)))    (capi:prompt-with-list     (recipes-can-make ingredients recipe-database)     “You can make these:”)))

保存和加载数据库

最后,这是将数据库保存到磁盘上的文件的过程:

(defun save-recipes ()  (with-open-file (stream “Recipes” :direction :output :if-exists :supersede)    (write ingredient-database :stream stream)    (write recipe-database :stream stream)))

并将它们加载回:

(defun load-recipes ()  (with-open-file (stream “Recipes” :direction :input)    (setf ingredient-database (read stream))    (setf recipe-database (read stream))))

http://mip.i3geek.com

Leave a Reply

搜索

分类目录

公 告

本网站学习论坛:

www.zhlisp.com

lisp中文学习源码:

https://github.com/zhlisp/

欢迎大家来到本站,请积极评论发言;

加QQ群学习交流。