Suppose I want to delete one step (element) from the states list.
(defparameter *states* '((:top nil nil) (:subjects nil nil)))
;predicate
(defun equal-state? (step state)
(equal (car step) state))
If I use (delete-if #'equal-state? *states*) then how the second argument ( state) can be passed to predicate?
edited: I have finally found a similar question but I am inclined to retain it because of clarity in the question.
CL-USER 67 > (let ((state :top))
(delete-if (lambda (step)
(equal-state? step state))
*states*))
((:SUBJECTS NIL NIL))
or
CL-USER 68 > (defun make-predicate (state)
(lambda (step)
(equal-state? step state)))
MAKE-PREDICATE
CL-USER 69 > (delete-if (make-predicate :subjects)
*states*)
((:TOP NIL NIL))
As user coredump mentions, delete-if is a potentially destructive operation. The non-destructive alternative to delete-if is remove-if.
One can also use remove/ delete:
CL-USER 77 > (remove :subjects
'((:top nil nil)
(:subjects nil nil))
:key #'first
:test #'equal)
((:TOP NIL NIL))
Related
The task was to Create an XLISP program that simulates the stack implementation of push and pop. Remember, the push and pop of a stack happens only on the top of stack (which is different from a queue)
In this case, we assume that the right most part of your list is the top portion.
Push operation description
Ask the user to enter a number
Insert the data into your stack
0 or negative number is not allowed. If so, simply print "Invalid Input"
Pop
Simply removes the top data from your stack.
Assumption:
You have a list called mystack initialized as an empty list.
Example Run:
(setq myStack())
NIL
(push)
*** When I try to run the code it says that undefined function NIL
(setq myStack(nil))
> (push)
> (pop)
; PUSH Function
(defun push ()
(let ((num (read)))
(if (and (numberp num) (> num 0))
(setq myStack (append myStack (list num)))
(print "Invalid Input"))))
; POP Function
(defun pop ()
(if (null myStack)
(print "Stack is empty")
(progn
(setq myStack (butlast myStack))
(print myStack))))
Your Problem first of all is
(setq myStack (nil))
In Common Lisp, one would write it:
(defparameter *my-stack* nil)
In Common Lisp, there is the equality: NIL == () == '() == 'NIL.
What you want is an empty list, which is one of those.
Remember, an empty list () or '() already contains an implicit NIL
as its last CDR. Proof:
(cdr ()) ;; => NIL
(cdr '()) ;; => NIL
(cdr NIL) ;; => NIL
(cdr 'NIL) ;; => NIL
At least in Common Lisp it is defined like this.
However, in Racket/Scheme this is not defined like this. Therefore, this is not universal to Lisps:
$ racket
Welcome to Racket v6.11.
> (cdr NIL)
; NIL: undefined;
; cannot reference undefined identifier
; [,bt for context]
> (cdr '())
; cdr: contract violation
; expected: pair?
; given: '()
; [,bt for context]
> (cdr ())
; readline-input:4:5: #%app: missing procedure expression;
; probably originally (), which is an illegal empty application
; in: (#%app)
; [,bt for context]
> (cdr 'NIL)
; cdr: contract violation
; expected: pair?
; given: 'NIL
; [,bt for context]
Therefore, in XLISP this must not be ...
However, for all lisps, it will be true that you need '() as an empty list.
So at least, your line must be:
(setq my-stack '())
If you forget the quote ', the interpreter/compiler thinks it is a function call and searches the function name nil and doesn't find it. Therefore your error.
Later you ask in your pop function: (null my-stack). If you start with '(nil), the problem is you don't start with an empty list.
Proof:
In Common Lisp:
(null '(nil)) ;;=> nil
In Racket:
(null? '(nil)) ;;=> #f
Why? because your list then contains still and element which has as value NIL.
In both languages, you can do:
(cdr '(nil)) ;;=> '() <-- Now the list is empty!
I would define your push und pop in Common Lisp:
(defparameter *my-stack* '())
(defun my-push (x)
(setf *my-stack* (cons x *my-stack*))
(defun my-pop ()
(let ((x (car *my-stack*)))
(setf *my-stack* (cdr *my-stack*))
x))
As you see I don't append it at the end because this is very inefficient (otherwise one has to traverse the entire list).
In Lisp, one adds at the start by cons-ing. And pops from the start by car-ing and cdr-ing.
Also, your pop doesn't return the pop-ed value.
Actually, your function to behave like the in-built push and pop in Common Lisp, must be:
(defmacro my-push (x lst)
`(setf ,lst (cons ,x ,lst)))
(defmacro my-pop (lst)
`(let ((x (car ,lst)))
(setf ,lst (cdr ,lst))
x))
Usage:
(defparameter *stack* '())
(my-push 1 *stack*) ;;=> (1)
(my-push 2 *stack*) ;;=> (2 1)
(my-push 3 *stack*) ;;=> (3 2 1)
*stack* ;;=> (3 2 1)
(my-pop *stack*) ;;=> 3
(my-pop *stack*) ;;=> 2
(my-pop *stack*) ;;=> 1
(my-pop *stack*) ;;=> NIL
(my-pop *stack*) ;;=> NIL
;; whether the list is empty or the first element's value is NIL
;; you can check by (length *stack*) => if that is 0, the stack is empty
In racket:
(define-syntax-rule (push x lst)
(set! lst (cons x lst)))
(define-syntax-rule (pop lst)
(let ((x (car lst)))
(set! lst (cdr lst))
x))
Usage:
> (define stack '())
> (push 1 stack)
> (push 2 stack)
> (push 3 stack)
> stack
'(3 2 1)
> (pop stack)
3
> (pop stack)
2
> (pop stack)
1
> (pop stack)
; car: contract violation
; expected: pair?
; given: '()
; [,bt for context]
so I have a program:
(defun add (L)
(cond((endp L) nil)
(t(cons(1+(first L)))(add(rest L)))))
that will add 1 to each member of the list. I want to check if the list is all numbers and return nil if not, and don't know how to go about doing that within the defun.
I thought of doing
(defun add (L)
(cond((endp L) nil)
((not(numberp(first L))) nil)
(t(cons(1+(first L)))(add(rest L)))))
but that will still return the beginning of the list if the non number is in the middle. How would I pre check and return nil at the beginning?
You can wrap it in a condition-case
(defun add (L)
(condition-case nil
(mapcar '1+ L)
(error nil)))
Another possibility is to use iteration:
(defun add (l)
(loop for x in l
if (numberp x)
collect (1+ x)
else do (return-from add nil)))
The function is immediately exited with nil on the first non numeric element.
You would not implement iteration using recursion, since Lisp already provides iteration constructs. Example: MAPCAR.
Common Lisp also provides control flow constructs like RETURN-FROM, where you return from a block. A function defined by DEFUN has a block with its name and BLOCK can also create a named block explicitly. Examples for both:
CL-USER 62 > (block mapping
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from mapping nil)))
'(1 2 3 nil 5 6)))
NIL
CL-USER 63 > (block mapping
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from mapping nil)))
'(1 2 3 4 5 6)))
(2 3 4 5 6 7)
As function:
CL-USER 64 > (defun increment-list (list)
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from increment-list nil)))
list))
INCREMENT-LIST
CL-USER 65 > (increment-list '(1 2 3 4 5 6))
(2 3 4 5 6 7)
CL-USER 66 > (increment-list '(1 2 3 nil 5 6))
NIL
I'd say that an idiomatic way, in Common Lisp, of checking that all elements in a list are numbers would be (every #'numberp the-list), so I would probably write this as:
(defun add-1 (list)
(when (every #'numberp list)
(mapcar #'1+ list)))
It would be possible to use (if ...) or (and ...), but in this case I would argue that (when ...) makes for the clearest code.
The difficulty is that propagating nil results in the nil at the end of the list causing everything to be nil. One solution is to check that add returns nil but (rest xs) is not nil. However, IMO it is more straightforward to just iterate over the list twice, checking for numbers the first time and then doing the addition on the second iteration.
Try this:
(defun add (xs)
(cond ((endp xs) nil)
((not (numberp (car xs))) nil)
(t (let ((r (add (rest xs))))
(cond ((and (not r) (rest xs)) nil)
(t (cons (1+ (first xs)) r)))))))
Barring mistakes on my end, this results in:
(add '()) => nil
(add '(1 2)) => '(2 3)
(add '(x y)) => nil
(add '(1 2 y)) => nil
EDIT: Without let. This results in 2^(n+1)-1 calls to add for a list of length n.
(defun add (xs)
(cond ((endp xs) nil)
((not (numberp (car xs))) nil)
(t (cond ((and (not (add (rest xs))) (rest xs)) nil)
(t (cons (1+ (first xs)) (add (rest xs)))))))))
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)
Is there a case where gensym's feature of appending unique numbers to the prefix comes in handy? I don't get why there is gensym when
(let ((str "batman"))
(eq (make-symbol str)
(make-symbol str)))
always returns nil.
GENSYM for example makes debugging generated code slightly easier.
Example:
See this expansion of a LOOP macro. You can see which symbols are the same by looking at their names, even though they are not interned in a package. There are two uninterned temp variables. Different names now make the use clear.
CL-USER 4 > (pprint (macroexpand '(loop for i in '(1 2 3) sum i)))
(BLOCK NIL
(MACROLET ((LOOP-FINISH () '(GO #:|end-loop-1103|)))
(LET ((I NIL) (#:|tail-1106| '(1 2 3)) (#:|by-1107| 'SYSTEM:CDR$CONS))
(LET ((#:|accumulator-1104| 0))
(DECLARE (TYPE NUMBER #:|accumulator-1104|))
(TAGBODY
#:|begin-loop-1102| NIL
(PROGN
(WHEN (OR (ENDP #:|tail-1106|)) (GO #:|end-loop-1103|))
(LET ((#:|temp-1109| (FUNCALL #:|by-1107| #:|tail-1106|))
(#:|temp-1108| (SYSTEM:CAR$CONS #:|tail-1106|)))
(SETQ I #:|temp-1108|)
(SETQ #:|tail-1106| #:|temp-1109|)))
(INCF #:|accumulator-1104| I)
(GO #:|begin-loop-1102|)
#:|end-loop-1103| (RETURN-FROM NIL #:|accumulator-1104|))))))
I am trying to write a function (lnn; list-not-nil) similar to list that only appends values that are not nil.
(list nil 3) --> (NIL 3)
(lnn nil 3) --> (3)
Here is the code I have so far. For some reason it causes infinite recursion on any input that I try.
(defun lnn (&rest items)
(lnn-helper nil items))
(defun lnn-helper (so-far items)
(cond ((null items)
so-far)
((null (car items))
(lnn-helper so-far (cdr items)))
(t (lnn-helper (append so-far (list (car items))) (cdr items)))))
Any ideas? Thanks very much.
(defun lnn-helper (so-far &rest items)
...)
With this argument list, items will never be nil if you always call lnn-helper with two arguments. Remove the &rest specifier, and it'll work.
Matthias' answer should have helped. Also note, that this is just a simple reduction:
(defun lnn (&rest elements)
(reduce (lambda (elt acc) (if elt (cons elt acc) acc))
elements
:from-end t
:initial-value nil))
Or even (less efficient):
(defun lnn (&rest elements)
(reduce #'cons (remove nil elements) :from-end t :initial-value nil))
Then:
(defun lnn (&rest elements)
(remove nil elements))
:)
P.S.: I know this was probably just an exercise in recursion, but SCNR.