I am creating a expert system with Common Lisp for my study.
There is a global variable : BF -> fact base.
I initialize like that :
(defvar *BF* NIL)
My "main function" call to the function "initialize" which set the global variable with big data.
(defun initialize ()
(setf *BF*
'(
(metric (
(CPU-utilization NIL)
(RPI NIL)
(ART NIL)
(concurent-invocation NIL)
(stall-count NIL)
(GC-bytes-in-use NIL)
(available-thread NIL)
(available-connection NIL)
(instance-count NIL)
))
(problem (
(livelock T)
(memory-leaks T)
(code-inefficient T)
(overload T)
(under-allocation T)
(internal-chokepoint T)
(thread-leaks T)
(blocking-deadlock T)
(unending-retries T)
(overuse-external-system T)
(pig-in-a-python T)
(too-many-layers T)
(backend-bottleneck T)
(frequent-GC-resource-leaks T)
(slow-backend T)
(suddenly-slow-backend T)
(nonblocking-deadlock T)
(thread-leaks T)
))
(category (
(sudden T)
(consistent T)
(periodic T)
(progressive T)
))
)
)
)
In the first use of this function, when i print BF, it's ok.
Then I call a function wich modify BF :
(defun apply-rule (type name value)
; Get conclusion list for this rule
(let ((conclusion (get-conclusion name value)))
(if (null conclusion)
(if (not (equal 3 value))
(return-from appliquer-regle NIL)
(return-from appliquer-regle 'T)
)
)
; Iterate on all problems in *BF*
(dolist (e (cadr (assoc 'problem *BF*)))
; If the problem is not in conclusion list, set it value to false
(if (and (member (car e) conclusion) (equal (cadr e) 'T))
()
(setf (cadr e) NIL)
)
)
(return-from apply-rule 'T)
)
(return-from apply-rule NIL)
)
This function work.
But when I want to use again the function "initialize", it doesn't work. When I print BF, it contain the old values ...
How can I do to reinitialize my global variable ?
Sorry for my english, I'm french ^
You are modifying literal data. It's best to avoid it, since its effects are undefined in portable code. Imagine a compiler which saves space by sharing literal lists.
Make sure that your variable *BF* has freshly allocated data. Use COPY-TREE to copy the list every time you initialize the variable.
Related
I'm trying to make a code in lisp to count occurrences of atoms in a list in lisp.
The problem is the code works for all atoms except the atom (), which appears as NIL.
Example in the code:
(defun flatten (list_)
(cond ((atom list_) (list list_))
((null list_) NIL)
(t (append (flatten (car list_)) (flatten (cdr list_))) )
)
)
(defun toUniqueList (list_ out)
(cond ((null list_) NIL)
((not (member (car list_) out)) (append (list (car list_)) (toUniqueList (cdr list_) (append (list (car list_)) out)) ))
(t (toUniqueList (cdr list_) out))
)
)
(defun countOccurences (list_ x)
(cond ((null list_) 0)
((eql (car list_) x) (+ (countOccurences (cdr list_) x) 1))
(t (countOccurences (cdr list_) x))
)
)
(defun countOccurencesAll (list_)
(setq flatList (flatten list_))
(setq parsed (toUniqueList flatList '()))
(setq result '())
(dolist (x parsed)
(setq result (append result (list (list x (countOccurences flatList x)) ))))
result
)
(write (countOccurencesAll '(x y z 4.6 (a x) () (5 z x) ())))
; ((X 3) (Y 1) (Z 2) (4.6 1) (A 1) (NIL 5) (5 1))
Any idea in how to show () rather than NIL?
The expressions nil, 'nil, (), and '() all gets evaluated to nil which is displayed as nil unless it is the cdr of a pair in which it will just close the list. eg. '(() . ()) gets evaluated to (NIL . NIL) and it is displayed as (NIL). There is nothing you can do about that.
So the question is then, because ((a) (()) (c)) is really ((a . nil) . ((nil . nil) . ((c . nil) . nil))) should it count nil/() 5 times or ignore when nil in the cdr of a pair and just count it as one?
BTW using setq in countOccurencesAll on undefined bindings means your code is in the mercy of the implementation. The hyperspec does not define how it should be handled and SBCL makes warnings about how it interprets the code and other might just choose an interpretation. A better approach would be to use let to define the bindings. Using a hash and iterate over the list once would make an O(n) solution.
I have a Lisp program that's going through nested list and deleting elements that match the element passed through to the function. My issue is, if everything in one of the nested list is deleted, I need to print out () instead of NIL.
(defun del (x l &optional l0)
(cond ((null l) (reverse l0))
((if (atom x) (eq x (car l)) (remove (car l) x)) (del x (cdr l) l0))
(T (del x (cdr l) (cons (if (not (atom (car l)))
(del x (car l))
(car l))
l0)))))
(defun _delete(a l)
(format t "~a~%" (del a l)))
(_delete 'nest '(nest (second nest level) (third (nest) level)))
This returns
((SECOND LEVEL (THIRD NIL LEVEL))
And I need
((SECOND LEVEL (THIRD () LEVEL))
I've tried using the ~:S format but that apparently doesn't work with composite structures. I've also tried the substitute function to replace NIL, also with no results.
Two possible solutions:
I. You can use the format directives ~:A or ~:S
(format t "~:a" '()) => ()
However, this directive works only on the top level elements of a list, i.e.
(format t "~:a" '(a b () c))
will not print (A B () C)
but (A B NIL C)
So you need to loop through the list applying the ~:A to each element recursively if it is a cons.
(defun print-parentheses (l)
(cond ((consp l) (format t "(")
(do ((x l (cdr x)))
((null x) (format t ")" ))
(print-parentheses (car x))
(when (cdr x) (format t " "))))
(t (format t "~:a" l)) ))
(print-parentheses '(a b (c () d))) => (A B (C () D))
II. Create a print-dispatch function for empty lists and add it to the pretty print dispatch table:
(defun print-null (stream obj)
(format stream "()") )
(set-pprint-dispatch 'null #'print-null)
(print '(a () b)) => (A () B)
The latter is simpler, but it affects all the environment, which might not be what you want.
We can write an :around method for print-object, for the case when the object to be printed is NIL.
(defvar *PRINT-NIL-AS-PARENS* nil
"When T, NIL will print as ().")
(defmethod print-object :around ((object (eql nil)) stream)
(if *print-nil-as-parens*
(write-string "()" stream)
(call-next-method)))
(defun write-with-nil-as-parens (list)
(let ((*print-nil-as-parens* t))
(write list)))
Example:
CL-USER 73 > (write-with-nil-as-parens '(a b c nil (()) (nil)))
(A B C () (()) (())) ; <- printed
(A B C NIL (NIL) (NIL)) ; <- return value
I've also tried the substitute function to replace NIL, also with no results.
None of the standard substitution functions will work. substitute is a sequence processing function: it will not recurse into the tree structure.
The sublis and subst functions will process the tree structure, but they treat the car and cdr fields of conses equally: if we replace nil throughout a tree structure with :whatever, that applies to all of the terminating atoms, so that (a nil b) becomes (a :whatever b . :whatever).
We must make our out function which is like subst, but only affects car-s:
(defun subcar (old new nested-list)
(cond
((eq nested-list old) new)
((atom nested-list) nested-list)
(t (mapcar (lambda (atom-or-sublist)
(subcar old new atom-or-sublist))
nested-list))))
With this, we can replace nil-s with the character string "()":
[1]> (subcar nil "()" '(a b c nil (e nil f (g nil)) nil))
(A B C "()" (E "()" F (G "()")) "()")
If we pretty-print that, the character strings just print as the data rather than as machine-readable string literals:
[2]> (format t "~a~%" *) ;; * in the REPL refers to result of previous evaluation
(A B C () (E () F (G ())) ())
I hope you understand that nil and () mean exactly the same thing; they are the same object:
[3]> (eq nil ())
T
The only way the symbol token nil can denote an object other than () is if we we are in a package which hasn't imported the nil symbol from the common-lisp package (and nil is interned as a local symbol in that package, completely unrelated to cl:nil):
[1]> (defpackage "FOO" (:use))
#<PACKAGE FOO>
[2]> (in-package "FOO")
#<PACKAGE FOO>
Sanity test: from within package foo check that cl:nil is the same as the () object. We have to refer to the eq function as cl:eq because package foo doesn't import anything from cl:
FOO[3]> (cl:eq cl:nil ())
COMMON-LISP:T
Now let's see if nil in this package is ():
FOO[4]> (cl:eq nil ())
*** - SYSTEM::READ-EVAL-PRINT: variable NIL has no value
OOPS! This is not the standard nil anymore; it doesn't have special the behavior that it evaluates to itself. We must quote it:
FOO[6]> (cl:eq 'nil ())
COMMON-LISP:NIL
Nope, not the () object. Note how the return values of the cl:eq function are printed as COMMON-LISP:NIL or COMMON-LISP:T. Symbols are printed without a package prefix only if they are present in the current package.
I am new to lisp and I'm trying to a simple check to see if a list is empty. For test purposes i created this test function:
(defun test (list)
(if (null (caddr list))
(make-node 1)
(caddr list)))
if uses the make-node function defined as:
(defun make-node (atm)
(cons atm `(`() `())))
when running (make-node 6) I get:
(6 (QUOTE NIL) (QUOTE NIL))
which is what I want.
i then call (test (make-node 6)) which i then get:
(QUOTE NIL)
which is the (caddr list) from test. if you run (null (QUOTE NIL)) you get T which is what i want to get but when i run it from the given test function i receive NIL.
So my question is why when i check if this is null why do i get NIL instead of T?
When you evaluate (null (quote nil)), (quote nil) is evaluated, resulting in nil being used as the argument for the function null.
However when you evaluate something like (null (function-returning-quote-nil)), function-returning-quote-nil is evaluated, resulting in the list (quote nil) which is then used as the argument for the function null without further evaluation.
Compare to the difference between
(null (quote nil)) ; => t
and
(null '(quote nil)) ; => nil
(CADDR '(6 (QUOTE NIL) (QUOTE NIL))) ; ==> (QUOTE NIL) or just 'NIL
The list with the two symbols QUOTE and NIL are not equal to NIL. Only NIL is equal to NIL. eg.
(DEFPARAMETER TEST 'NIL)
TEST ; ==> NIL
(NULL TEST) ; ==> T
This works since 'NIL gets evaluated to NIL and assigned to TEST. TEST gets evaluated to NIL and it's CLs NULL value. However:
(DEFPARAMETER TEST2 ''NIL)
TEST2 ; ==> 'NIL or (QUOTE NIL)
(NULL TEST2) ; ==> NIL
A list with two elements QUOTE and NIL, famously displayed as 'NIL, is NOT NIL. Only NIL is NIL.
EDIT
After looking at your comments about unquoting I'm pretty sure you want this as make-node:
(defun make-node (atm)
(cons atm '(() ())))
(test (make-node 6)) ; ==> (1 NIL NIL)
There is no such thing as unquoting in a data structure and unless you actually want the symbol quote in your data there is no sense in having quotes inside something quoted. (Half truth since there is, but it involves macros)
(print x) prints exactly what I want to eval, but (eval x) fails,
but if I run x it works! What am I missing?
Please tell me why this doesn't work, or if I'm doing something stupid.
I'm trying to print a table of dynamic size and setting lambda variables to eventually evaluate an expression for each cell in the table.
BTW I figured out why eval fails. (eval x) is losing the macrolet, but WHY?!
This works:
(defvar varlist '(a b c d))
(defvar vvars '(c d))
(defvar hvars '(a b))
(macrolet ((AlternateVariable (var &rest body)
`(dolist (,var '(nil t)) ,#body))
(AlternateVariables (varlist &rest body)
(if (null varlist)
(cons 'progn body)
`(AlternateVariable ,(car varlist)
(AlternateVariables ,(cdr varlist) ,#body)))))
(let ((listvarlist (cons 'list varlist)))
(print
`(AlternateVariables ,(reverse vvars)
(AlternateVariables ,(reverse hvars)
(format t "row=~S~%" ,listvarlist) ))))
nil)
and it prints what I want it to:
(alternatevariables (d c)
(alternatevariables (b a) (format t "row=~S~%" (list a b c d))))
If I change that "print" to "eval" I get
; in: alternatevariables (d c)
; (B A)
; caught warning:
; undefined variable: a
but if I run what it printed (inside the macrolet) it works!
(macrolet ((AlternateVariable (var &rest body)
`(dolist (,var '(nil t)) ,#body))
(AlternateVariables (varlist &rest body)
(if (null varlist)
(cons 'progn body)
`(AlternateVariable ,(car varlist)
(AlternateVariables ,(cdr varlist) ,#body)))))
(alternatevariables (d c)
(alternatevariables (b a) (format t "row=~S~%" (list a b c d))))
nil)
and it prints
row=(nil nil nil nil)
row=(t nil nil nil)
row=(nil t nil nil)
row=(t t nil nil)
row=(nil nil t nil)
row=(t nil t nil)
row=(nil t t nil)
row=(t t t nil)
row=(nil nil nil t)
row=(t nil nil t)
row=(nil t nil t)
row=(t t nil t)
row=(nil nil t t)
row=(t nil t t)
row=(nil t t t)
row=(t t t t)
nil
I have heard "eval is evil" but I need the backquote to get the right evaluation order and evaluate some arguments but not others. Print is a good debug tool, but then I'm missing something with eval. Does eval lose the macrolet?
! That's it. I defined those two macrolet macros as defmacros and then eval works!
Why?! Eval is losing the macrolet. (I'm new to macrolet and no lisp genius)
Or, how do I do this without eval?
Any general notes on my code would be nice too. Is this over complicated?
Also, errors in macros seem to get awkward error messages. Any help with that?
$ sbcl
This is SBCL 1.1.2-1.fc18, an implementation of ANSI Common Lisp.
EVAL in Common Lisp only evaluates in a current dynamic environment and the null lexical environment. Enclosing it in lexical constructs like MACROLET, LET, ... or similar is not going to work.
I am trying to define a recursive function balanced that takes a string and returns true only if the parens in the string are balanced.
The elisp code I wrote is based on some Scala code I wrote for the Coursera class by Odersky, it's a transliteration.
;; check if expr (list of chars of some expression) is balanced
(defun balanced (expr)
(defvar lparen (string-to-char "("))
(defvar rparen (string-to-char ")"))
(defun is-open (c) (eq lparen c))
(defun is-close (c) (eq rparen c))
(defun is-empty (ls) (eq ls nil))
(defun is-matching (l r) (and (is-open l) (is-close r)))
(defun is-balanced (list stack)
(cond ((is-empty list) (is-empty stack))
((is-open (car list))
(is-balanced (cdr list) ;; 'push' open-paren onto stack
(cons (car list) stack)))
((is-close (car list))
(if (is-empty stack) nil
(and
(is-balanced (cdr list) (cdr stack))
(is-matching (car stack) (car list)))))
(is-balanced (cdr list) (cdr stack))))
is-balanced
I am in lisp-interaction-mode, so I used Ctrl-J to evaluate the above defun statement.
Then, when I attempt to evaluate this:
(balanced "(balanced nil nil)")
I get a void-variable error:
Debugger entered--Lisp error: (void-variable is-balanced)
balanced("(balanced nil nil)")
(progn (balanced "(balanced nil nil)"))
eval((progn (balanced "(balanced nil nil)")) t)
eval-last-sexp-1(t)
eval-last-sexp(t)
eval-print-last-sexp()
call-interactively(eval-print-last-sexp nil nil)
recursive-edit()
debug(error (void-variable is-balanced))
balanced("(balanced nil nil)")
(progn (balanced "(balanced nil nil)"))
eval((progn (balanced "(balanced nil nil)")) t)
eval-last-sexp-1(t)
eval-last-sexp(t)
eval-print-last-sexp()
call-interactively(eval-print-last-sexp nil nil)
recursive-edit()
The function doesn't seem to recognize itself, what am I doing wrong?
When you execute your function (balanced ...), what it does is this:
It first defines two global variables
It defines five other functions
It accesses the variable is-balanced.
Step 3. happens right after the end of (defun is-balanced (list stack) ... )))).
(defun balanced (expr)
...
(defun is-balanced (list stack)
...
(is-balanced (cdr list) (cdr stack))))
is-balanced ;; <= here!
But you have not defined such a variable. You have defined a function of the same name, but you cannot access function objects as if they're variables in Emacs Lisp. See also here. Since there is no variable named is-balanced you get an error message.
(That said, there's a lot to be critized about the rest of your code. For starters, be aware that by having defuns inside defuns, you're re-defining your is-* functions every single time you're invoking (balanced ...). That's certainly not what you want. Similarly, you probably want to move the defvar outside the function body, since they define global variables. Or did you mean to use (let ...) instead? If you really want global values, then (defconst...) might be more appropriate.)
The problem is that the final element of the cond expression is not wrapped in (t ... ):
Incorrect:
(is-balanced (cdr list) (cdr stack))
Correct
(t (is-balanced (cdr list) (cdr stack)))
The reason this is needed is that the last expression is supposed to be the else case.