strange behaviour of (delete .. in Allegro Lisp - common-lisp

I try to remove random elements from a list until the list is empty. My environment is Allegro Lisp, free edition.
(setq set1 '(Nr1 Nr2 Nr3))
(delete (nth (random (length set1)) set1) set1)
After some repetitions, the output of sequential calls to delete (and the content of set1) start to look like this:
(NR1 NR2 NR3)
(NR2 NR3)
(NR1 NR2)
(NR1)
NIL
That is, sometimes items are not deleted, sometimes deleted items reappear. If I use remove there is no such problem.
Is this a bug or do I miss something about delete?

delete is allowed to destroy/mutate/reuse parts of the original list to return the result, this has two implications:
You should use (setf set1 (delete ...))
Mutating a quoted list is not a good idea, just use (setf set1 (list 'Nr1 'Nr2 'Nr3)) instead

When delete is asked to remove the first element of a list, it is allowed to simply return (cdr list), you need to (setf set1 (delete (nth (random (length set1)) set1)))

Related

Define a constant array of struct known at compilation-time

In my program I have constant strings, the values are known at compilation time. For each offset there are currently 2 associated strings. I first wrote the following code:
(eval-when (:compile-toplevel :load-toplevel :execute) ;; BLOCK-1
(defstruct test-struct
str-1
str-2))
(eval-when (:compile-toplevel) ;; BLOCK-2
(defparameter +GLOBAL-VECTOR-CONSTANT+ nil) ;; ITEM-1
(let ((vector (make-array 10
:initial-element (make-test-struct)
:element-type 'test-struct)))
(setf (test-struct-str-1 (aref vector 0)) "test-0-1")
(setf (test-struct-str-2 (aref vector 0)) "test-0-2")
(setf +GLOBAL-VECTOR-CONSTANT+ vector)))
(format t "[~A]~%" (test-struct-str-1 (elt +GLOBAL-VECTOR-CONSTANT+ 0)))
(format t "[~A]~%" (test-struct-str-2 (elt +GLOBAL-VECTOR-CONSTANT+ 0)))
This seems to work as it returns the following:
[test-2-1]
[test-2-2]
In BLOCK-1 the struct containing the data is defined, for compile-time, load-time and execute-time. In BLOCK-2, the code which create a vector and sets the values is executed, at compile-time.
But I have the following concerns:
This code seems unnecessary verbose
The strings are stored in a structure
I need to manually set the offset of each values ((aref vector 0), (aref vector 1), etc).
When I set ITEM-1 inside BLOCK-1 instead of BLOCK-2 I get an error in SBCL which I don't understand
What is the idiomatic way to define complex constants in Common Lisp?
It's not really clear what you want to do from your question.
First important note: your code is seriously broken. It's broken because you define +global-vector-constant+ only at compile time but refer to it later than that. If you compile this file and then load that compiled file into a cold image you will get errors.
It is absolutely critical when dealing with things like this to make sure that your code will compile in a cold Lisp. One of the classic problems with resident environments (which CL isn't really, compared to the way Interlisp-D was for instance) is to end up with systems which you can't cold build: I'm pretty sure I worked for several years with an Interlisp-D sysout that no-one knew how to cold build any more.
If what you want is an object (an array, for instance) whose initial value is computed at compile time and then treated as a literal, then the answer to that is, in general, a macro: macros are exactly functions which do their work at compile time, and so a macro can expand to a literal. In addition it must be the case that the object you want to be a literal is externalizable (which means 'can be dumped in compiled files') and anything involved in it is known about at compile time. Instances of some classes are externalizable by default, those of some other classes can be made externalizable by user code, and some are not externalizable at all (for instance functions).
In quite a lot of simple cases, like the one you gave, if I understand it, you don't really need a macro, and in fact you can almost always get away without one, although it may make your code easier to understand if you do use one.
Here is a simple case: many arrays are externalizable if their elements are
(defparameter *my-strings*
#(("0-l" . "0-r")
("1-l" . "1-r")))
This means that *my-strings* will be bound to a literal array of conses of strings.
A more interesting case is when the elements are, for instance structures. Well, structures are also externalizable, so we can do that. And in fact it's quite possible, still, to avoid a macro, although it now becomes a bit noisy.
(eval-when (:compile-toplevel :load-toplevel :execute)
(defstruct foo
l
r))
(defparameter *my-strings*
#(#s(foo :l "0-l" :r "0-r")
#s(foo :l "1-l" :r "1-r")))
Note that the following won't work:
(defstruct foo
l
r)
(defparameter *my-strings*
#(#s(foo :l "0-l" :r "0-r")
#s(foo :l "1-l" :r "1-r")))
It won't work because, at compile time, you are trying to externalize instances of a structure which is not yet defined (but it probably will work if the Lisp is not cold, and you might even be able to reload the compiled file you made that way). Again, in this case you can avoid the eval-when in a larger system by ensuring that the file which defines the foo structure is compiled and loaded before the file with the defparameter is loaded.
And even in more complex cases you can escape using a macro. For instance for many sorts of objects which are normally not externalizable you can teach the system how to externalize them, and then splice the object in as a literal using #.:
(eval-when (:compile-toplevel :load-toplevel :execute)
;; Again, this would be in its own file in a bigger system
(defclass string-table-wrapper ()
((strings)
(nstrings :initform 0)))
(defmethod initialize-instance :after ((w string-table-wrapper)
&key (strings '()))
(let ((l (length strings)))
(when l
(with-slots ((s strings) (n nstrings)) w
(setf s (make-array l :initial-contents strings)
n l)))))
(defmethod make-load-form ((w string-table-wrapper) &optional environment)
(make-load-form-saving-slots w :slot-names '(strings nstrings)
:environment environment))
) ;eval-when
(defgeneric get-string (from n)
(:method ((from string-table-wrapper) (n fixnum))
(with-slots (strings nstrings) from
(assert (< -1 n nstrings )
(n)
"bad index")
(aref strings n))))
(defparameter *my-strings*
#.(make-instance 'string-table-wrapper
:strings '("foo" "bar")))
Note that, of course, although the value of *my-strings* is a literal, code ran to reconstruct this object at load-time. But that is always the case: it's just that in this case you had to define what code needed to run. Instead of using make-load-form-saving-slots you could have done this yourself, for instance by something like this:
(defmethod make-load-form ((w string-table-wrapper) &optional environment)
(declare (ignore environment))
(if (slot-boundp w 'strings)
(values
`(make-instance ',(class-of w))
`(setf (slot-value ,w 'strings)
',(slot-value w 'strings)
(slot-value ,w 'nstrings)
,(slot-value w 'nstrtrings)))
`(make-instance ',(class-of w))))
But make-load-form-saving-slots is much easier.
Here is an example where a macro does perhaps least make reading the code easier.
Let's assume you have a function which reads an array of strings from a file, for instance this:
(defun file-lines->svector (file)
;; Needs CL-PPCRE
(with-open-file (in file)
(loop
with ltw = (load-time-value
(create-scanner '(:alternation
(:sequence
:start-anchor
(:greedy-repetition 1 nil
:whitespace-char-class))
(:sequence
(:greedy-repetition 1 nil
:whitespace-char-class)
:end-anchor)))
t)
for nlines upfrom 0
for line = (read-line in nil)
while line
collect (regex-replace-all ltw line "") into lines
finally (return (make-array nlines :initial-contents lines)))))
Then, if this function is available at macroexpansion time, you could write this macro:
(defmacro file-strings-literal (file)
(check-type file (or string pathname) "pathname designator")
(file-lines->svector file))
And now we can create a literal vector of strings:
(defparameter *fl* (file-strings-literal "/tmp/x"))
However you could perfectly well instead do this:
(defparameter *fl* #.(file-lines->svector "/tmp/x"))
Which will do the same thing, but slightly earlier (at read time, rather than at macroexpansion/compile time). So this is gaining nothing really.
But you could also do this:
(defmacro define-stringtable (name file &optional (doc nil docp))
`(defparameter ,name ,(file-lines->svector file)
,#(if docp (list doc) nil)))
And now your code reads like
(define-stringtable *st* "my-stringtable.dat")
And that actually is a significant improvement.
Finally note that in file-lines->svector that load-time-value is used to create the scanner exactly once, at load time, which is a related trick.
First of all, your let code can be simplified to
(defparameter +global-vector-constant+
(let ((vector ...))
...
vector))
Second, you can also do
(defparameter +global-vector-constant+
(make-array 10 :element-type 'test-struct :initial-content
(cons (make-test-struct :str-1 "test-0-1" :str-2 "test-0-2")
(loop :repeat 9 :collect (make-test-struct)))))
Note that the benefit of :element-type 'test-struct is generally limited to code self-documentation (see upgraded-array-element-type)

LISP How to create a database storing function parameters

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:
You give the program the name of a function and it should return the function parameters.
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?
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.
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.

return the second to last list element in common lisp

I am trying to learn common lisp through paradigms of artificial intelligence. one of the exercises in the book was to define a function that would return the last name of a given list without a certain suffix or word. As an example if the list contained bruce banner, phd it would return banner. here is my solution, however this would still return the last element regardless if it was a suffix or not
(Defun last-name (name)
(if (member (last name) *suffix*)
(Last-name (butlast name))
(last name)))
where
(defparameter *suffix* '( MD PHD DR))
a similar exercise was presented in the book omitting a prefix in a list using 'rest' instead of 'butlast' and returning the first element. That worked perfectly fine.
(defparameter *titles* '( Mr MRS MS SIR MADAM DR ADMIRAL MAJOR GENRAL ))
(Defun first-name (name)
(if (member (first name) *titles*)
(first-name (rest name))
(first name)))
I am not sure if I am missing anything in the last-name function or if my logic is incorrect. Any help is greatly appreciated!
Apologies if the text is long, it is my first post and I was not sure what level of detail I should include.
Thank you.
The reason is that last does not return the last element of a list, but a list containing the last element. That is:
(last '(bruce banner phd))
;; -> (PHD), not PHD
Actually, last gets an optional argument n after the list, argument which is set to 1 by default, and returns a list with the last n elements of the first parameter (see the manual).
So the function member does not return true.
Try to change the function in:
(defun last-name (name)
(if (member (car (last name)) *suffix*)
(Last-name (butlast name))
(car (last name))))

lisp nested if statements

Hi im making a song database using Common lisp, im try to check the song information is well formed- ie it has 6 element in the list of song information, but I also want to check the types of each element in the list. I'm trying to do this using if statements, by first checking that there are 6 elements and if there are then checking the type of each element.
(defun checkSongInfo (par1 par2)
(if (= 6 (length (nth par1 par2))
(if (intergerp (first (nth par1 par2)))) 'complete 'incomplete))
so basically I have this code to begin with, I honestly have just started using LISP and am not familiar with it. Basically what im trying to do here is check for the 6 elements and if this is successful the success outcome of the if statement should be to then check the first element of the list, the song and list are passed in as parameters, these parts of my code should work as I have tried typing them directly into the terminal and they do what they should. The problem is with the if statements, at the moment it is telling me I have too few parameters. The first if statement works when I do
if(=6 (length (nth par1 par2))) 'complete 'incomplete
But when I put in the other if statement it give me the you have to few parameter for the if statement operator error message. It is probably just down to my misunderstanding of LISP and I have been searching for ages and cannot come up with a solution.
You are having problems with your parentheses and you have probably misspelled integerp in your code. I think you wanted to do this:
(defun checkSongInfo (par1 par2)
(if (= 6 (length (nth par1 par2))) ; added a ) here
(if (integerp (first (nth par1 par2))) ; removed a ) here, intergerp => integerp
'complete
'incomplete))) ; added a ) here
Looking at this you'll get incomplete if it's 6 elements and fails the second test but NIL if it's not 6 elements. You can use and and or instead of nesting ifs if more than one test needs to pass for something to be T. I would have used and here, like this:
(defun checkSongInfo (par1 par2)
(if (and (= 6 (length (nth par1 par2)))
(integerp (first (nth par1 par2))))
'complete
'incomplete))
This returns either complete if both tests passes and incomplete otherwise.
The else form is optional with if. Stylistically, if there is no else expression you'd use when.
(defun checkSongInfo (par1 par2)
(when (= 6 (length (nth par1 par2))) ; You're missing a ) here.
(if (intergerp (first (nth par1 par2)))
'complete
'incomplete))) ; Also missed a ) here.

Modifying a list passed as a parameter gives different results in SBCL and CLISP

Can someone explain why I get different results for the following simple program with sbcl and clisp? Is what I am doing undefined by the language, or is one of the two lisp interpreters wrong?
; Modify the car of the passed-in list
(defun modify (a) (setf (car a) 123))
; Create a list and print car before and after calling modify
(defun testit () (let ((a '(0)))
(print (car a))
(modify a)
(print (car a))))
(testit)
SBCL (version 1.0.51) produces:
0
0
CLISP (version 2.49) produces (what I would expect):
0
123
I agree with Seth's and Vsevolod's comments in that this behavior is due to your modification of literal data. Try using (list 0) instead of '(0). Questions relating to this come up relatively frequently, so I'll quote the HyperSpec here.
3.7.1 Modification of Literal Objects:
The consequences are undefined if literal objects are destructively
modified.
The definition of "literal":
literal adj. (of an object) referenced directly in a program rather
than being computed by the program; that is, appearing as data in a
quote form, or, if the object is a self-evaluating object, appearing
as unquoted data. ``In the form (cons "one" '("two")), the expressions
"one", ("two"), and "two" are literal objects.''
Note that often (in many implementations), if you modify literal values, you'll really modify them in the code itself – writing self modifying code. Your example code will not work as you expect.
Your example code in CCL:
CL-USER> (defun modify (a) (setf (car a) 123))
MODIFY
CL-USER> (defun testit ()
(let ((a '(0)))
(print (car a))
(modify a)
(print (car a))))
TESTIT
CL-USER> (testit)
0
123
123
CL-USER> (testit)
123
123
123
Take a look at the second evaluation of testit, where the let itself really already contains the modified value, thus the first print also yields 123.
Also see: Lisp, cons and (number . number) difference, where I explained this in more detail, or the question linked in Vsevolod's comment above.

Resources