I'm new to Lisp so when I wrote the function in SBCL
(defun subst (new old l)
(cond
((null l) '())
((eq old (car l)) (cons new (cdr l)))
((cons (car l) (subst new old (cdr l))))))
it gives error SYMBOL-PACKAGE-LOCKED-ERROR,a Style-Warning and a Warning, please help to resolve it
You're trying to redefine cl:subst. According to §11.1.2.1.2 of the HyperSpec, it's undefined what happens when you try to do that. Most implementations have some sort of package lock which prevents such redefinitions. You can get around those, by unlocking the package, but it would be better in this case to either use a name other than subst (e.g., my-subst), or to define a new package, say my-cl, that shadows cl:subst and define my-cl:subst instead.
The error that SBCL gives is actually rather informative and provides a reference to the HyperSpec page that I linked to above, as well as the Chapter 11. Package Locks from the SBCL manual:
* (defun subst (new old l)
(cond
((null l) '())
((eq old (car l)) (cons new (cdr l)))
((cons (car l) (subst new old (cdr l))))))
; in: DEFUN SUBST
; (SB-INT:NAMED-LAMBDA SUBST
; (NEW OLD L)
; (BLOCK SUBST (COND ((NULL L) 'NIL) ((EQ OLD #) (CONS NEW #)) ((CONS # #)))))
; ==>
; #'(SB-INT:NAMED-LAMBDA SUBST
; (NEW OLD L)
; (BLOCK SUBST
; (COND ((NULL L) 'NIL) ((EQ OLD #) (CONS NEW #)) ((CONS # #)))))
;
; caught STYLE-WARNING:
; The definition has no &KEY arguments, but the proclamation did.
; (SUBST NEW OLD (CDR L))
;
; caught WARNING:
; recursion in known function definition
; policy=((COMPILATION-SPEED . 1) (DEBUG . 1) (INHIBIT-WARNINGS . 1)
; (SAFETY . 1) (SPACE . 1) (SPEED . 1))
; arg types=(T T T)
;
; compilation unit finished
; caught 1 WARNING condition
; caught 1 STYLE-WARNING condition
STYLE-WARNING: redefining COMMON-LISP:SUBST in DEFUN
debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR in thread #<THREAD
"initial thread" RUNNING
{1002978E71}>:
Lock on package COMMON-LISP violated when setting fdefinition of SUBST while
in package COMMON-LISP-USER.
See also:
The SBCL Manual, Node "Package Locks"
The ANSI Standard, Section 11.1.2.1.2
Related
I am writing a function called ptyper that takes a nested list, nl. This function replaces all occurrences of a number with n and all occurrences of a symbol with s. This is what I have now:
(define (ptyper nl) (cond
((null? nl) '())
((list? nl)
(let ((ls (car nl)))
(list (ptyper ls))))
((number? (car nl))
(cons "n" (cdr nl)))
((symbol? (car nl))
(cons "s" (cdr nl)))
(else
(cons (car nl) (cdr nl)))))
I ran this test (ptyper '(2 (abc () "abc"))) but received an error that their was a contract violation. I'm not exactly sure what I'm doing wrong so if could use some help. Thanks!
Here is a possible solution with one function:
(define (ptyper nl)
(cond
((null? nl) '()) ; if the argument is an empty list, return the empty list
((list? nl) ; if the argument is a list, then
(let* ((c (car nl)) ; get its first element
(nc (cond ((number? c) "n") ; transform it for numbers
((symbol? c) "s") ; and symbols
((list? c) (ptyper c)) ; if a list recur over it
(else c)))) ; otherwise (e.g. a string) return as it is
(cons nc (ptyper (cdr nl))))) ; recursive call on the rest of the list
(else nl))) ; this should never happen for the specification,
; return the parameter or cause an error
Note that the error in your case is caused by the recursive call. When the function is called on an atom, for instance 2, first it checks for null and list?, and those checks returns false. Then it checks for (number (car nl)), but nl is equal to 2 and so car fails.
Here is a data definition for an S-expression, this models your data.
; An S-expr is one of:
; – Atom
; – SL
; An SL is one of:
; – '()
; – (cons S-expr SL)
; An Atom is one of:
; – Number
; – String
; – Symbol
We have predicates for every kind of data except Atom, so we make atom?:
;; Any -> Boolean
;; is the x an atom?
(define (atom? x)
(not (list? x)))
We follow the structure of the data to build "templates" for our functions:
(define (func sexp)
(cond
[(atom? sexp) (func-atom sexp)]
[else (func-sl sexp)]))
(define (func-sl sl)
(cond
[(empty? sl) ...]
[else (... (func (first sl)) ... (func-sl (rest sl)) ...)]))
(define (func-atom at)
(cond
[(number? at) ...]
[(string? at) ...]
[(symbol? at) ...]))
We fill in the gaps:
; Atom -> String
(define (subs-atom at)
(cond
[(number? at) "n"]
[(string? at) at]
[(symbol? at) "s"]))
; SL -> SL
(define (subs-sl sl)
(cond
[(empty? sl) sl]
[else (cons (subs-sexp (first sl))
(subs-sexp (rest sl)))]))
; S-exp -> S-exp
(define (subs-sexp sexp)
(cond
[(atom? sexp) (subs-atom sexp)]
[else (subs-sl sexp)]))
Using the interface for ptyper:
(define (ptyper nl)
(subs-sexp nl))
(ptyper '(2 (abc () "abc")))
; => '("n" ("s" () "abc"))
I'm trying to implement quicksort in CLisp, and so far I'm able to partition the list around a pivot. However, when I try to combine and recursively sort the sublists, I get either a stack overflow or an error with let, and I'm not sure what's going wrong. Here's my code:
(defun pivot (n xs)
(list (getLesser n xs) (getGreater n xs))
)
(defun getLesser (m l)
(cond
((null l) nil)
((<= m (car l)) (getLesser m (cdr l)))
(t (cons (car l) (getLesser m (cdr l)))))
)
(defun getGreater (m l)
(cond
((null l) nil)
((> m (car l)) (getGreater m (cdr l)))
(t (cons (car l) (getGreater m (cdr l)))))
)
(defun quicksort (xs)
(cond
((null xs) nil)
(t
(let (partition (pivot (car xs) xs))
(cond
((null (car partition)) (cons (quicksort (cdr partition)) nil))
((null (cdr partition)) (cons (quicksort (car partition)) nil))
(t (append (quicksort (car partition)) (quicksort (cdr partition)))))))))
My idea was to have a local variable partition that is a list of 2 lists, where car partition is the list of number less than the pivot, and cdr partition is the list of numbers greater than the pivot. Then, in the final cond construct, if there were no numbers less than the pivot I would recursively sort the 2nd list; if there were no numbers greater than the pivot I would sort the 1st list; else I would recursively sort both and append them in order. Can anyone help me out?
Compiling the file gives you hints about wrong syntax.
GNU CLISP produces these diagnostics:
$ clisp -q -c foo.lisp
;; Compiling file /tmp/foo.lisp ...
WARNING: in QUICKSORT in lines 20..28 : Illegal syntax in LET/LET*: (PIVOT (CAR XS) XS)
Ignore the error and proceed
;; Deleted file /tmp/foo.fas
There were errors in the following functions:
QUICKSORT
1 error, 1 warning
SBCL produces similar diagnostics:
$ sbcl --eval '(compile-file "foo.lisp")' --quit
This is SBCL 1.3.1.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
; compiling file "/tmp/foo.lisp" (written 08 MAY 2019 08:58:54 PM):
; compiling (DEFUN PIVOT ...)
; compiling (DEFUN GETLESSER ...)
; compiling (DEFUN GETGREATER ...)
; compiling (DEFUN QUICKSORT ...)
; file: /tmp/foo.lisp
; in: DEFUN QUICKSORT
; (LET (PARTITION (PIVOT (CAR XS) XS))
; (COND ((NULL (CAR PARTITION)) (CONS (QUICKSORT #) NIL))
; ((NULL (CDR PARTITION)) (CONS (QUICKSORT #) NIL))
; (T (APPEND (QUICKSORT #) (QUICKSORT #)))))
;
; caught ERROR:
; The LET binding spec (PIVOT (CAR XS) XS) is malformed.
;
; compilation unit finished
; caught 1 ERROR condition
; /tmp/foo.fasl written
; compilation finished in 0:00:00.021
You can then look up the expected syntax in CLHS: http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/speope_letcm_letst.html
The syntax for LET is (LET BINDINGS . BODY), where BINDINGS is a list of bindings; each binding is a (SYMBOL VALUE) list. Alternatively, a binding can just be SYMBOL, which stands for (SYMBOL NIL). Your code is:
(let (partition (pivot (car xs) xs))
...)
Let's write one binding per line and normalize all bindings as a proper list:
(let ((partition nil)
(pivot (car xs) xs)))
...)
You can see that the code:
binds partition to NIL
has a malformed second binding: there are three elements, namely pivot, (car xs) and xs, which does not match the expected (SYMBOL VALUE) syntax.
Here is my function
(defun freq (symbol_A List_L)
(cond ((atom (car List_L))
(cond ((eq (car List_L) symbol_A) t (+ 1 (freq symbol_A (cdr List_L))))
(t 0)))
(T (freq symbol_A (cdr List_L))))
)
I am getting an error variable ATOM has no value. Here is what I am testing with
(freq 'c '((a c) c e)) --> 2
(freq 'f '(((s) o ) d)) --> 0
(freq 'f '(((f) f) f f)) --> 4
Can not understand where is my error.
I also tried this:
(defun freq (a L)
(cond
((null L) 0)
((equal a (car L)) (+ 1 (freq a (cdr L))))
(t (freq a (cdr L)))))
Knowing that nil is an atom, you can simply recurse over the car and cdr of each cons cell. When you hit an atom, add 1 if it matches or 0 if it doesn't.
(defun freq (sym tree)
(if (atom tree)
(if (eq sym tree) 1 0)
(+ (freq sym (car tree)) (freq sym (cdr tree)))))
There is a syntax error in your code.
Indent and format your code
First you need to format your code:
(defun freq (A L)
(cond (atom (car L)) ; first clause
(eq A (car (car L ))) ; second clause
(T (+ 1 (freq A (cdr L)))) ; third clause
(T (freq A (cdr L))))) ; fourth clause
A useful COND:
(cond ((> i 0) :positive)
((< i 0) :negative)
(t :equal))
You have written something like:
(cond (> i 0) :positive
(< i 0) :negative
(t :equal))
Here a Lisp interpreter would complain that > has no value. It's because it is used as a variable. (> i 0) is seen as the first clause and the test form is the variable >. Since > usually is not a variable, this is an error.
A compiler might even reject the whole form at compile time, since there are clauses which are not lists.
As you can see the parentheses around a clause are missing in your code.
Check the syntax of cond...
cond {clause}* => result*
A cond has zero or more clauses.
clause::= (test-form form*)
Each clause is a list (!!) starting with a test-form and followed by zero or more forms.
It makes also no sense to have two clause with T as the test form. The first one will always be take and the second one will always be ignored.
I am getting an error "variable EQ has no value" when I run the following code. How to overcome this error?
(defun add_book(bookref title author publisher)
(setf (get bookref 'title) title)
(setf (get bookref 'author) author)
(setf (get bookref 'publisher) publisher)
(setq library (cons bookref library))
bookref)
(defun retrieve_by (property value)
(setq result nil)
(do ((L library (cdr L)))
((NULL L) result)
(cond (EQ (get (car L) property) value)
(cons (car L) result))))
Maybe better formatting and the output from the SBCL compiler will help you. See the compiler warnings. Try to consult the Lisp reference to look up the syntax of the various constructs: http://lispdoc.com
* (defun add_book(bookref title author publisher)
(setf (get bookref 'title) title)
(setf (get bookref 'author) author)
(setf (get bookref 'publisher) publisher)
(setq library (cons bookref library))
bookref)
; in: DEFUN ADD_BOOK
; (SETQ LIBRARY (CONS BOOKREF LIBRARY))
;
; caught WARNING:
; undefined variable: LIBRARY
;
; compilation unit finished
; Undefined variable:
; LIBRARY
; caught 1 WARNING condition
ADD_BOOK
* (defun retrieve_by (property value)
(setq result nil)
(do ((L library (cdr L)))
((NULL L) result)
(cond (EQ (get (car L) property) value)
(cons (car L) result))))
; in: DEFUN RETRIEVE_BY
; (COND (EQ (GET (CAR L) PROPERTY) VALUE) (CONS (CAR L) RESULT))
; --> IF COND
; ==>
; (IF CONS
; (PROGN (CAR L) RESULT)
; NIL)
;
; caught WARNING:
; undefined variable: CONS
; ==>
; (IF EQ
; (PROGN (GET (CAR L) PROPERTY) VALUE)
; (COND (CONS (CAR L) RESULT)))
;
; caught WARNING:
; undefined variable: EQ
; (DO ((L LIBRARY (CDR L)))
; ((NULL L) RESULT)
; (COND (EQ (GET (CAR L) PROPERTY) VALUE) (CONS (CAR L) RESULT)))
; --> BLOCK
; ==>
; (LET ((L LIBRARY))
; (TAGBODY
; (GO #:G1)
; #:G0
; (TAGBODY (COND (EQ # VALUE) (CONS # RESULT)))
; (PSETQ L (CDR L))
; #:G1
; (UNLESS (NULL L) (GO #:G0))
; (RETURN-FROM NIL (PROGN RESULT))))
;
; caught WARNING:
; undefined variable: LIBRARY
; (SETQ RESULT NIL)
;
; caught WARNING:
; undefined variable: RESULT
;
; compilation unit finished
; Undefined variables:
; CONS EQ LIBRARY RESULT
; caught 4 WARNING conditions
RETRIEVE_BY
*
"define a procedure 'reduce-per-key' which a procedure reducef and a list of associations in which each key is paired with a list. The output is a list of the same structure except that each key is now associated with the result of applying reducef to its associated list"
I've already written 'map-per-key' and 'group-by-key' :
(define (map-per-key mapf lls)
(cond
[(null? lls) '()]
[else (append (mapf (car lls))(map-per-key mapf (cdr lls)))]))
(define (addval kv lls)
(cond
[(null? lls) (list (list (car kv)(cdr kv)))]
[(eq? (caar lls) (car kv))
(cons (list (car kv) (cons (cadr kv) (cadar lls)))(cdr lls))]
[else (cons (car lls)(addval kv (cdr lls)))]))
(define (group-by-key lls)
(cond
[(null? lls) '()]
[else (addval (car lls) (group-by-key (cdr lls)))]))
how would I write the next step, 'reduce-per-key' ? I'm also having trouble determining if it calls for two arguments or three.
so far, I've come up with:
(define (reduce-per-key reducef lls)
(let loop ((val (car lls))
(lls (cdr lls)))
(if (null? lls) val
(loop (reducef val (car lls)) (cdr lls)))))
however, with a test case such as:
(reduce-per-key
(lambda (kv) (list (car kv) (length (cadr kv))))
(group-by-key
(map-per-key (lambda (kv) (list kv kv kv)) xs)))
I receive an incorrect argument count, but when I try to write it with three arguments, I also receive this error. Anyone know what I'm doing wrong?
Your solution is a lot more complicated than it needs to be, and has several errors. In fact, the correct answer is simple enough to make unnecessary the definition of new helper procedures. Try working on this skeleton of a solution, just fill-in the blanks:
(define (reduce-per-key reducef lls)
(if (null? lls) ; If the association list is empty, we're done
<???> ; and we can return the empty list.
(cons (cons <???> ; Otherwise, build a new association with the same key
<???>) ; and the result of mapping `reducef` on the key's value
(reduce-per-key <???> <???>)))) ; pass reducef, advance the recursion
Remember that there's a built-in procedure for mapping a function over a list. Test it like this:
(reduce-per-key (lambda (x) (* x x))
'((x 1 2) (y 3) (z 4 5 6)))
> '((x 1 4) (y 9) (z 16 25 36))
Notice that each association is composed of a key (the car part) and a list as its value (the cdr part). For example:
(define an-association '(x 3 6 9))
(car an-association)
> 'x ; the key
(cdr an-association)
> '(3 6 9) ; the value, it's a list
As a final thought, the name reduce-per-key is a bit misleading, map-per-key would be a lot more appropriate as this procedure can be easily expressed using map ... but that's left as an exercise for the reader.
UPDATE:
Now that you've found a solution, I can suggest a more concise alternative using map:
(define (reduce-per-key reducef lls)
(map (lambda (e) (cons (car e) (map reducef (cdr e))))
lls))