我要编写的一个小的Lisp程序应该执行以下操作(从我的旧问题中复制:LISP - Program to search a specific function through its parameters):
程序应以两种不同的方式工作:
您为程序指定一个函数名称,它应该返回函数参数。
您输入函数参数,如果存在带有这些参数的函数,则应返回该函数的名称。
我得到了以下代码:
(defun get-name-by-params (database params)
(let ((matching-entries (remove-if-not (lambda (entry)
(equal (second entry) params))
database)))
(mapcar #'first matching-entries)))
(defun get-params-by-name (database function)
(let ((matching-entries (remove-if-not (lambda (entry)
(equal (first entry) function))
database)))
(flatten(mapcar #'second matching-entries))))
(defun flatten (L)
(if (null L)
nil
(if (atom (first L))
(cons (first L) (flatten (rest L)))
(append (flatten (first L)) (flatten (rest L))))))
使用该代码,我得到以下结果:
(get-params-by-name '((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result)) 'append)
->(&REST LISTS)
(get-name-by-params '((cons (t t) cons) (list (&rest t) list)) '(&rest t))
->(LIST)
这两种情况正是我所需要的。我的任务的最后一个问题是,我需要创建一个存储函数和参数的数据库,因为我需要向程序中添加更多的函数。
所以我需要创建一个存储以下数据的数据库
'((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result))
,并且如果可能的话,可以由给定的函数处理。
有人可以举一个例子说明如何为此任务创建数据库吗?
答案 0 :(得分:0)
对于实验性项目和快速项目,我倾向于使用仅存储s表达式的简单文本文件。
一个非常简单的数据库:
appsettings.Production.json
您可以使用一些简单的功能来查找条目。
要按(隐式)索引查找:
(format open-file-stream "~S" any-sexp)
要按键查找:
(注意:您存储密钥时,只需将其添加到存储在sexp结构中的sexp 任意位置中。以后,您可以通过提供相关的选择器功能来获取密钥,默认情况下假定成为(defun read-nth-sexp (n file)
(with-open-file
(file-stream file)
(loop for i from 0
for sexp = (read file-stream nil)
do (if (eq n i) (return sexp)))))
。)
#'car
这对多达10,000个或100,000个条目有效,具体取决于您的硬件。我在处理超过五十万个条目时遇到了困难。
我不需要更新数据,因此我从未编写过任何更新函数,但是它们可以轻松编写。
对于非常快速的搜索,假设您的数据具有可排序的属性,那么我在二进制搜索方面取得了成功。
答案 1 :(得分:0)
您可以使用持久性存储数据库来设计Lisp数据库,而可以使用持久性存储数据库来设计数据库,并且可以以序列化格式保存数据以加载/保存数据库。您会感到惊讶,但有些大公司,例如Yahoo!相对于使用持久数据库(例如MySQL),它在90年代就做到了,而今天许多人仍然这样做。如果您想用Lisp编写数据库,这是程序结构的示例。您可以使用CLOS将函数存储为该类的实例。您说您需要函数名称和函数参数。因此,您可以使用属性“名称”和“参数”创建一个类。这是一个示例:
(defclass functions()
((name :accessor func-name
:initarg :name)
(params :accessor func-params
:initarg :params
:initform '(nil))))
我们可以如上所述创建一个带有用于名称和参数的插槽的类,然后我们可以创建该类的实例。因此,例如,如果我有这样的功能:
(defun foo (n lst)
(list foo))
我可以创建一个这样的实例...
(defvar func-1 (make-instance 'functions
:name "foo"
:params '("n" "lst")))
如果我有这样的功能:
(defun foo-2(lst n)
(list lst n))
我可以这样创建另一个实例:
(defvar func-2 (make-instance 'functions
:name "foo-2"
:params '("lst" "n")))
现在我们如何将这些实例存储在数据库中?我们有一些选择,但是一个简单而通用的示例是将实例存储在列表中。我们可以使用Macros来增加复杂性,甚至创建我们自己的嵌入式SQL语言形式,但是为了简单起见,我们可以仅使用列表和find函数来创建临时数据库。这是一个数据库示例和两个函数,这些函数根据一个函数名称或参数来搜索该数据库:
(defvar *func-db* nil) ;Create an empty list to store the functions
(push func-1 *func-db*)
(push func-2 *func-db*) ;Push a couple of functions to the DB
(defun find-params (name)
(func-params
(find name *func-db*
:test #'string-equal
:key #'func-name)))
(defun find-name (param-list)
(func-name
(find param-list *func-db*
:test #'equal
:key #'func-params))
现在,我们可以创建几个函数,以根据搜索的名称查找函数的参数,或者根据输入的参数查找函数的名称。在这种情况下,我将使用字符串进行简单说明,但是您可能应该使用符号。以下是一些有关如何搜索数据库的示例:
CL-USER> (find-params "foo")
("n" "lst")
CL-USER> (find-params "foo-2")
("lst" "n")
CL-USER> (find-name '("n" "lst"))
"foo"
CL-USER> (find-name '("lst" "n"))
"foo-2"
这就是我们如何在Lisp中建立一个临时数据库的方法。一本好书是“ Practical Common Lisp”。有一个免费的在线版本,在那本书中,主要项目之一是创建MP3数据库。最简单的示例是使用列表存储信息,然后进行搜索。如果要保存数据库以备后用,可以将其保存到文件中,然后在再次使用时加载它。这项技术看似简单,但是我已经看到大公司将其与MySQL进行比较。您甚至可以创建自己的嵌入式SQL语言来搜索信息,并且由于信息存储在内存中,因此,如果您决定扩展此项目并在Lisp中创建Web应用程序,则其检索结果的速度甚至比MySQL还要快。