【问题标题】:LISP How to create a database storing function parametersLISP 如何创建存储函数参数的数据库
【发布时间】:2019-03-18 18:46:26
【问题描述】:

我要编写的一个小 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))

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

谁能给我一个如何为这个任务创建数据库的例子?

【问题讨论】:

  • 是否可以只使用defparameter?类似 "(defparameter functionlist '((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result)))?
  • 是的,它是这样工作的。
  • 您可能喜欢持久(lisp)对象数据库:github.com/CodyReichert/awesome-cl#persistent-object-databases 创建 SQL 数据库的教程:lispcookbook.github.io/cl-cookbook/databases.html
  • 正如上面提到的海报,我想知道您是否可以通过创建一个字面上存储函数的数据库,然后使用 SQL 语法查询该数据库来解决这个问题?这意味着要么在 Lisp 中创建一个数据库(这可能很有趣),要么使用一个持久性数据库。
  • 您好,我认为为此使用任何类型的持久性数据库都太过分了。您可能想查看诸如 PCL gigamonkeys.com/book/practical-an-mp3-database.htmlgithub.com/Wukix/LambdaLite 之类的内容。两者都需要根据您的目的进行一些修改,但将是一个很好的起点

标签: common-lisp


【解决方案1】:

对于实验性和快速项目,我倾向于使用仅存储 s 表达式的简单文本文件。

一个非常简单的数据库:

(format open-file-stream "~S" any-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)))))

按键查找: (注意:存储密钥时,只需将其添加到 sexp 结构中的 sexp anywhere 即可存储它。稍后您可以通过提供相关的选择器函数来获取它,默认情况下假定为成为#'car。)

(defun find-entry (entry file &key (select #'car))
  (with-open-file 
    (file-stream file) 
    (loop for sexp = (read file-stream nil)
      while sexp
      do (if (equal (funcall select sexp) entry)
             (return sexp)))))

这适用于多达 10,000 或 100,000 个条目,具体取决于您的硬件。我在处理超过 50 万个条目时遇到了困难。


我不需要更新我的数据,因此我从未编写过任何更新函数,但它们很容易编写。

对于非常快速的搜索,我在二进制搜索方面取得了成功,假设您的数据当然具有可排序的属性。

【讨论】:

    【解决方案2】:

    您可以在 Lisp 中设计数据库,而不是使用持久存储数据库,并且可以以序列化格式保存数据,以便加载/保存数据库。您会感到惊讶,但有些大公司,例如 Yahoo!在 90 年代就这样做了,今天仍然有许多人这样做,而不是使用诸如 MySQL 之类的持久数据库。如果您想用 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")))
    

    现在我们如何将这些实例存储在数据库中?我们有几个选项,但一个简单且通用的示例是将实例存储在列表中。我们可以增加复杂性,甚至可以使用宏创建我们自己的嵌入式 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 中制作临时数据库的方法。一本好书是“实用通用 Lisp”。有一个免费的在线版本,在那本书中,主要项目之一是创建一个 MP3 数据库。最简单的例子是使用 List 来存储信息,然后搜索它。如果您想保存数据库以供以后使用,可以将其保存到文件中,然后在您想再次使用时加载它。这种技术可能看起来很简单,但我已经看到大公司使用它与 MySQL 对比。您甚至可以创建自己的嵌入式 SQL 语言来搜索信息,并且由于信息存储在内存中,如果您决定扩展此项目并在 Lisp 中创建 Web 应用程序,它可以比 MySQL 更快地检索结果。

    【讨论】:

      猜你喜欢
      • 2013-10-24
      • 2011-05-22
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多