2

A little lisp program i got to write should do the following (copied from my old question: LISP - Program to search a specific function through its parameters):

The program should work in 2 different ways:

  1. You give the program the name of a function and it should return the function parameters.

  2. You enter function parameters and if a function with these parameters exists, it should return the name of the function.

I got the following code:

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

With that code i get the following results:

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

That is in both cases exactly what i need. My last problem with my task is that i need to create a database in which the functions and parameters are stored because i will need to add many more functions to the program.

So i need to create a database which stores the following data

'((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result))

and, if possible, can be processed by the given functions.

Could anybody please give me an example how to create a database for this task?

5
  • Would it be possible to just use defparameter? Something like "(defparameter functionlist '((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result)))? Commented Mar 19, 2019 at 6:58
  • Yes it works this way. Commented Mar 19, 2019 at 19:06
  • You might like persisent (lisp) object databases: github.com/CodyReichert/awesome-cl#persistent-object-databases A tutorial to create an SQL database: lispcookbook.github.io/cl-cookbook/databases.html Commented Mar 20, 2019 at 14:04
  • As the poster above mentioned, I was wondering if you could go about this by creating a database that literally stored the functions, and then querying that database with SQL syntax? That’d mean either creating a database in Lisp (which might be fun) or using a persistent database. Commented Mar 21, 2019 at 19:03
  • Hi there, I think that using any sort of persistant database for this would be pretty much overkill. You might want to look at things like PCL gigamonkeys.com/book/practical-an-mp3-database.html or something like github.com/Wukix/LambdaLite. Both would require some modification for your purposes but would be a good place to start Commented Mar 21, 2019 at 21:53

2 Answers 2

0

For experimental and quick projects, I tend to use a simple text file that just stores the s-expression.

A very simple database:

(format open-file-stream "~S" any-sexp)

You can look up an entry using some simple functions.

To look up by (implicit) index:

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

To find by key: (Note: You store the key by just adding it to the sexp anywhere in the structure of the sexp, when you stored it. Later you can get at it by providing the relevant selector function, by default assumed to be #'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)))))

This works well for upto 10,000's or maybe 100'000s of entries, depending on your hardware. I've had difficulty dealing with anything above half million entries.


I haven't had the need to update my data, and so I never wrote any updation functions but they can be written easily.

For very fast search, I've had success with binary search assuming of course your data has sortable properties.

Sign up to request clarification or add additional context in comments.

Comments

0

You could design a database in Lisp vs. using a persistent storage database, and you could save the data in a serialized format in order to load/save the database. You'd be surprised, but some big companies such as Yahoo! did this in the 90's, and many still do it today, vs. using a persistent database such as MySQL. Here is an example of the structure of the program if you want to write the database in Lisp. You could use the CLOS to store functions as instances of that class. You say that you need the function name, and the function parameters. So you could create a class with the attributes "name" and "parameters". Here is an example:

 (defclass functions()
   ((name :accessor func-name
      :initarg :name)
    (params :accessor func-params
        :initarg :params
        :initform '(nil))))

We can create a class with slots for the name and parameters as I showed above, and then we can create instances of that class. So if for example I have a function like this:

(defun foo (n lst)
    (list foo))

I can should create an instance like this...

 (defvar func-1 (make-instance 'functions
                   :name "foo"
                   :params '("n" "lst")))

And if I have a function like this:

(defun foo-2(lst n)
    (list lst n))

I can create another instance like this:

(defvar func-2 (make-instance 'functions
                   :name "foo-2"
                   :params '("lst" "n")))

Now how do we store these instances in a database? We have a few options, but a simple and general example would be to store the instances in a list. We could increase the complexity, or even create our own form of an embedded SQL language using Macros, but to keep it simple, we can just use a list and the find function in order to create a make-shift database. Here is an example of a database and two functions to search that database based on a functions name or parameters:

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

Now we can create a couple of functions to find the params of a function based on the name we search, or find the name of a function based on the params we enter. I will use Strings in this scenario for a simple illustration, but you should probably use symbols. Here are a couple of examples of how we would search the DB:

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"

That is how we can make a make-shift database in Lisp. A good book to read would be "Practical Common Lisp". There's a free online version, and in that book, one of the main projects is creating an MP3 database. The most simple example is using a List to store information and then searching it. If you want to save the database for later usage, you can save it to a file, and then load it when you want to use it again. This technique might seem simple, but I've seen big companies use it vs. MySQL. You can even create your own embedded SQL language to search for the information, and since the information is stored in memory it could retrieve results even faster than MySQL if you decided to extend this project and create a web application in Lisp.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.