LISP如何创建存储函数参数的数据库

时间:2019-03-18 18:46:27

标签: common-lisp

我要编写的一个小的Lisp程序应该执行以下操作(从我的旧问题中复制:LISP - Program to search a specific function through its parameters):

程序应以两种不同的方式工作:

  1. 您为程序指定一个函数名称,它应该返回函数参数。

  2. 您输入函数参数,如果存在带有这些参数的函数,则应返回该函数的名称。

我得到了以下代码:

(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))

,并且如果可能的话,可以由给定的函数处理。

有人可以举一个例子说明如何为此任务创建数据库吗?

2 个答案:

答案 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还要快。