Why does the following code return a nil value instead of 1?
(defun test (list)
(car(list)))
(test '( 1 2 3))
It returns nil because you're asking what the car of (list) is, which is a function invocation of the list function. Since you're passing the list function no arguments, it is returning nil since there is no car nor cdr (it's an empty list). The following would produce the desired effect:
(defun test (list)
(car list))
(test '(1 2 3)) ;; now returns 1
Related
I am new to lisp and I have a problem, I'm trying to find the number in the list but it is not working. I haven't made the return statement yet
(defun num (x 'y)
(if (member x '(y)) 't nil))
(write (num 10 '(5 10 15 20)))
My output just outputs the nil instead of doing the function and I'm confused of what I am doing wrong.
Solution
(defun member-p (element list)
"Return T if the object is present in the list"
(not (null (member element list))))
The not/null pattern is equivalent to (if (member element list) t nil) but is more common.
In fact, you do not really need this separate function,
member is good enough.
The -p suffix stands for predicate, cf. integerp and upper-case-p.
Your code
You cannot quote lambda list elements, so you need to replace defun num (x 'y) with defun num (x y)
You need not quote t
Quoting '(y) makes no sense, replace it with y.
You do not need to write the function call, the REPL will do it for you.
See also
When to use ' (or quote) in Lisp?
Can you program without REPL on Lisp?
You are almost certainly expected to not just use member, but to write a function which does what you need (obviously in real life you would just use member because that's what it's for).
So. To know if an object is in a list:
if the list is empty it's not;
if the head of the list is equal to the object it is;
otherwise it is in the list if it's in the tail of the list.
And you turn this into a function very straightforwardly:
(defun num-in-list-p (n l)
;; is N in L: N is assumed to be a number, L a list of numbers
(cond ((null l)
nil)
((= n (first l))
t)
(t
(num-in-list-p n (rest l)))))
You could use the built in position function which will return the index of the number if it is in the list:
(position 1 '(5 4 3 2 1))
If you want to define your own function:
CL-USER> (defun our-member(obj lst)
(if(zerop (length lst))
nil
(if(equal(car lst)obj)
T
(our-member obj (cdr lst)))))
OUR-MEMBER
CL-USER> (our-member 1 '(5 4 3 2 1))
T
CL-USER> (our-member 99 '(1 2 3 4 5))
NIL
We can create a function called "our-member" that will take an object (in your case a number) and a list (in your case a list of numbers) as an argument. In this situation our "base-case" will be whether or not the length of the list is equal to zero. If it is and we still haven't found a match, we will return nil. Otherwise, we will check to see if the car of the list (the first element in the list) is equal to the obj that we passed. If so, we will return T (true). However, if it is not, we will call the function again passing the object and the cdr of the list (everything after the car of the list) to the function again, until there are no items left within the list. As you can see, The first example of a call to this function returns T, and the second example call returns NIL.
What makes this utility function a good example is that it essentially shows you the under workings of the member function as well and what is going on inside.
I have a function and one macro in which the function is called.
And to see the difference, I trace the function and found that there was no difference whether it is called directly or from the macro.
I wonder why the parameter was not evaluated when called from macro.
I know that parameters passed to a macro will not be evaluated but even this happens to the parameters passed to a function from a macro?
To be specific, I mean why (< 7 5) is not evaluated to nil when passed to gen-lisp
The function:
(defun gen-lisp (expr binds)
expr)
The macro:
(defmacro dsptch-prove-query (query binds)
`(if (eq (car ',query) 'lisp)
,(gen-lisp (cadr query) binds)
(prove-query ',query ,binds)))
Result when called from macro:
(dsptch-prove-query (lisp (< 7 5)) nil)
1. Trace: (GEN-LISP '(< 7 5) 'NIL)
1. Trace: GEN-LISP ==> (< 7 5)
NIL
Result when called directly:
(gen-lisp '(< 7 5) 'NIL)
1. Trace: (GEN-LISP '(< 7 5) 'NIL)
1. Trace: GEN-LISP ==> (< 7 5)
(< 7 5)
And if I just do it like this below, it is evaluated to nil already.
(gen-lisp (< 7 5) nil)
1. Trace: (GEN-LISP 'NIL 'NIL)
1. Trace: GEN-LISP ==> NIL
NIL
Your macro is:
(defmacro dsptch-prove-query (query binds)
`(if (eq (car ',query) 'lisp)
,(gen-lisp (cadr query) binds)
(prove-query ',query ,binds)))
The macro calls the function gen-lisp. The arguments are computed by (cadr query) and binds. query is a list. (cadr query) computes the second element of that list. That's the evaluation going on. There is no reason why it should evaluate the result of (cadr query).
Remember: macros are getting source code passed. They compute with code.
Just passing the code around does not evaluate the code.
Your macro calls the function gen-lisp at macro-expansion time in order to compute a part of the macro-expansion.
The expression which calls the function is this:
(gen-lisp (cadr query) binds)
this is a function call, which specifies two argument expressions: (cadr query) and binds. These expressions most certainly are evaluated as forms and their resulting values constitute the arguments which the function receives.
The macro's query parameter's argument value is the nested list object (lisp (< 7 5)) and so (cadr query) calculates the object (< 7 5). Of course this itself isn't evaluated as a form. Evaluation is done, and (< 7 5) is its result, which gets passed into the function as its leftmost argument.
What's going on inside the macro is very similar to this:
(let ((query '(lisp (< 7 5))) ;; analogous to macro's query param
(binds nil))
(gen-lisp (cadr query) binds)) ;; of course (< 7 5) not evaled
If (< 7 5) were reduced to nil, that would be a double evaluation. Nothing in the code calls for a double evaluation. (For instance, we do not see any direct or indirect use of the eval function which could request that extra evaluation).
gen-lisp returns whatever argument it receives.
As a function, it does not evaluate its arguments.
If you want the argument to be evaluated, you should turn it into a macro (which you would probably want to do anyway when you start to use the binds argument in non-trivial way)
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)
I have the following common lisp functions: (aggregate line1 line2) and (queuer data result).
queuer should push into result either the values line1 and line2 if they have the 1st field different, or the aggregate of those 2 lines if they have the 1st field equal.
I do not know why it doesn't change my result list.
Note: I am initializing the result list with a (push (pop data) result) to have the first element there. The 2 lists are 1-depth nested lists (("1" "text") ("2" "text") (...)).
(defun aggregate (line1 line2)
(progn
(list
(nth 0 line1)
(nth 1 line1)
(nth 2 line1)
(concatenate 'string (nth 3 line1) ", " (nth 3 line2))
(concatenate 'string (nth 4 line1) ", " (nth 4 line2)))))
(push (pop x) y)
(defun queuer (data result)
(loop do
(let ((line1 (pop data))
(line2 (pop result)))
(if (equal (first line1) (first line2))
(progn
(push (aggregate line1 line2) result)
(print "=="))
(progn
(push line2 result)
(push line1 result)
(print "<>"))))
while data))
Thank you for any insights.
If you write functions in Lisp it is preferable to think 'functionally'. A function takes values and returns values. A typical rule would be to avoid side effects. So your function should return a result value, not 'modify' a variable value.
Instead of:
(defparameter *result* '())
(defun foo (a)
(push a *result*))
use:
(defparameter *result* '())
(defun foo (a result)
(push a result)
result)
(setf *result* (foo a *result*))
Note also that aggregate does not need the progn.
Slightly advanced (don't do that):
If you have a global list:
(defparameter *foo* '())
You can't push onto it, as we have seen, like this:
(defun foo (l)
(push 1 l))
If you call foo the variable *foo* is unchanged. Reason: Lisp does not pass a variable reference, it passes the value of the variable.
But how can we pass a reference? Well, pass a reference: a cons cell would do it (or a structure, a vector, a CLOS object, ...):
CL-USER 38 > (defparameter *foo* (list '()))
*FOO*
CL-USER 39 > (defun foo (ref)
(push 1 (first ref)))
FOO
CL-USER 40 > (foo *foo*)
(1)
CL-USER 41 > (foo *foo*)
(1 1)
Now, if we look at *foo*, it is changed. But we haven't really changed the variable. We have changed the first entry of the list.
CL-USER 42 > *foo*
((1 1))
But, don't do it. Program in a functional style.
You cannot modify the contents of a variable with a function that only takes the variable's value.
Take the following simple example:
(defun futile-push (thing list)
(push thing list))
(let ((foo (list 1)))
(futile-push 2 foo))
What happens?
Foo is evaluated to the list it points to.
2 evaluates to 2.
These two arguments are passed to the function.
Inside the function invocation:
Thing is now bound to 2.
List is now bound to the list (1).
Note that the list does not know that it is also referenced by the variable
foo outside the function.
foo
|
v
---------
list -> | 1 |NIL|
---------
Push modifies the variable list in such a way that it is now bound to
the list (2 1).
Note that this does not affect foo outside. Foo still points to
the same thing as before.
foo
|
v
--------- ---------
list -> | 2 | ----> | 1 |NIL|
--------- ---------
Futile-push returns the return value of the push form, which happens
to be the new value of list.
That return value is never used or bound, so it vanishes.
foo
|
v
---------
| 1 |NIL|
---------
The most straightforward way to do what you want is to return the new
value and then set the variable outside:
(let ((foo (list 1)))
(setf foo (not-so-futile-push 2 foo)))
If you need to do that at more than one place, it might be worthwhile
to write a macro for that which expands to the setf form. Note that
push is itself a macro for exactly these reasons.
When you call push in queuer, this changes the value of the binding "result", not the cons cell that result is pointing to.
(push x list)
is essentially equivalent to:
(setq list (cons x list))
As long as your queuer function is a function, it couldn't really be any other way. If you call it with the argument "my-queue", then that argument (a symbol) is evaluated when you call the function and the result of the evaluation -- a cons cell -- is passed to the function. There is no way to modify that cons cell to indicate that another cons cell should be "prepended" to it -- cons cells don't keep track of the things that point to them.
There are (at least) three possible solutions:
Write your code so that queuer returns the new queue, instead of expecting the argument to be modified (or "mutated").
Wrap the queue inside a mutable layer of indirection. You could for instance hold the queue in the car or the cdr of a cons cell. You would then be able to mutate (car result) or (cdr result) in your queuer function, for instance with push.
Convert queuer to be a macro instead of a function. You can then write code to mutate its argument that will essentially be 'inserted' in your code wherever you use the queuer macro.
I would personally recommend the first solution. Where you would then, if you had your mutating queuer, want to write:
(queuer-mutating data my-queue)
You would instead write something like:
(setf my-queue (queuer-not-mutating data my-queue))
When you initialize data variable using (push (pop data) result), it moves items from data to result instead of copying:
CL-USER> (setq data '(("1" "text1") ("2" "text2") ("3" "text3")))
(("1" "text1") ("2" "text2") ("3" "text3"))
CL-USER> (setq result nil)
NIL
CL-USER> (push (pop data) result)
;Compiler warnings :
; In an anonymous lambda form: Undeclared free variable DATA (3 references)
(("1" "text1"))
CL-USER> (print data)
(("2" "text2") ("3" "text3"))
(("2" "text2") ("3" "text3"))
CL-USER> (print result)
(("1" "text1"))
(("1" "text1"))
What you might want to use instead is (copy-list list) function:
CL-USER> (setq copy2 (copy-list data))
(("2" "text2") ("3" "text3"))
I wrote a test function to test my understanding of "return-from" in Lisp
(defun testp (lst)
(mapc #'(lambda (x y)
(if (null lst)
(return-from testp t)))
lst
(cdr lst)))
I think the test (testp 'nil) should return T but it returns NIL.
Could you please help my understanding of why it returns NIL?
Many thanks.
You call MAPC over two empty lists.
How should the LAMBDA function ever be used if the lists don't have any elements to map over?
Btw., you can write 'list' instead of 'lst'.
(defun testp (list)
(mapc #'(lambda (x y)
(if (null list)
(return-from testp t)))
list
(cdr list)))
Normally, mapc would apply your lambda to each element of a list. My guess (I don't use Common Lisp) is that since mapc has no elements in the list to operate on, your lambda never gets called at all, and as a result the return value of your function is the return value of mapc, which (since it mapped over nothing) is nil.