Of course I am a novice but why doesn't this return T?
(eql (third '(0 1 'to 0 1)) 'to)
==> nil
But this does return the quoted 'to.
(third '(0 1 'to 0 1))
'TO
As you might guess, none of the compare forms work, eq, eql, equal, equalp.
Because
'TO
is not EQL to
TO
The first is a list with two symbols as elements. It's actually (QUOTE TO).
The second is just a symbol.
? (EQL ''TO 'TO)
NIL
See:
? (equal (third '(0 1 'to 0 1)) ''TO)
T
You tried to quote a symbol in a literal list, which usually makes no sense, since literal lists are not evaluated inside.
Related
I was working on this question to print the sum of prime numbers in a range of numbers. The range values will be be taken as an input from the user. I got the syntax errors all cleared out but could not figure out how to return the value of the prime no. to the sum if it is true.
(defun check-prime(num)
(if (= num 1) nil)
;(setq i 2)
(loop for i from 2 to ( isqrt num) do
(if (= (mod num i) 0) nil t)
(= i (+ i 1))
)
)
(defun prime-sum(*begin* *end*)
(defvar *s* 0)
(defvar *i* *end*)
(loop for *i* from *end* to *begin* do
;i= 13
(if (check-prime *i*)
(= *s* (+ *s* *i* ) )
)
(= *i* (- *i* 1))
)
(write *s*)
)
(defun vals()
(print "enter the range1: ")
(defvar *begin* (read))
(print "enter the range2: ")
(defvar *end* (read))
(prime-sum *begin* *end*)
)
(print(vals))
;b =4
;e 13
Here is your function, cleaned up a bit and formatted in a conventional way:
(defun check-prime(num)
(if (= num 1) nil)
(loop
for i from 2 to (isqrt num)
do
(if (= (mod num i) 0) nil t)
(= i (+ i 1))))
There are multiple things that are incorrect, and they boil down to how are Lisp forms evaluated.
There is a special form progn in Common Lisp that is used to evaluate a list of expressions, with the following pattern:
(progn E1 E2 ... EN)
A lot of other functions in Lisp are described has having "an implicit progn", that's the case for defun which allows for more than one expression in its body, but since the progn doesn't appear literally it is implicit. The behavior is however always the same: each expression E1 to EN is evaluated in sequence, and evaluation of the whole progn are the values returned by the last expression, EN (that's where the N comes from in the name). In other words, the intermediate values from E1 etc. are discarded, the expressions are only useful for their side-effects.
In your code, that's the case for (if (= num 1) nil), which is an expression in the body of defun which is not the last one, and which doesn't even have side-effects. It is thus completely useless.
Likewise, in the loop macro, all that follows the do keyword are expressions that are evaluated for their side effects and do not contribute to the resulting value of the whole loop form.
In fact, loop is a bit complicated but here your don't have any accumulating clause in your loop (something like collect, append, sum etc. that would compute a result). Instead, your loop will always return nil.
Note also that for i from 2 to (isqrt num) takes care of incrementing i, you don't have to do it yourself like you tried in the do. Moreover, = is a comparison operator, in order to mutate i you would need to use setf instead: (setf i (+ i 1)), or (incf i) (which I repeat is unnecessary here).
To combine the first two expressions, I would write:
(if (= num 1) nil ...)
Where ... is the loop: because if is a functional if, it evaluates to whichever branch is selected by the condition.
And inside the loop, I would use never:
(loop for i from 2 to (isqrt num) never (= 0 (mod num i)))
The never clause makes the loop compute a boolean and halt as soon as the result is false.
it should count the elements of a list, but says "*** - +: NIL is not a number"
(setq A '(2 3 4 3 2 6 7 8 4 3 5 6))
(defun big (A)
(if (not (null (car A))) (+ 1 (big (cdr A))) ) ;if the first element is not null, add 1 to the count of the elements to the rest of the list
)
(print (big A))
Type error
An IF expression has either 2 or 3 arguments:
(if test something)
(if test something something-else)
When it only has 2 arguments, it is as-if the third argument, something-else, was NIL. That means that the IF expression evaluates to NIL when the test expression is false. In your case, you have 2 arguments:
(defun big (A)
(if (not (null (car A)))
;; "then" branch (when condition is true)
(+ 1 (big (cdr A)))
;; no "else" branch (when condition is false)
))
So you know that sometimes a call to big might return NIL.
But, you also write:
(+ 1 (big (cdr A)))
This expression looks like (+ 1 x) with x being a call to big, meaning that x might evaluate to NIL in some cases. That's the case you hit with the debugger.
If you make sure the if expression always return a number, by returning for example zero in the else branch, then you won't have the same error about trying to add a number to NIL.
Counting elements
But then, you would still have other bugs, since you say that the function big "should count the elements of a list". If you want to count the element of a list, you never need to look at the elements stored in the list, you only need to know that they exist.
When you write (car a), you are accessing the first element of the list. You then check if that value is non-nil, but it is perfectly valid to have a list filled with NIL values:
'(NIL NIL NIL)
That list has 3 elements, and at no point the fact that they are NIL should matter when counting them.
A recursive function working on a list typically needs to cover two cases, namely if the list is empty or not. You check if the current list is empty by calling (null list) or (endp list) (just doing (if list ... ...) works too since NIL is the only false value).
The test for null car doesn’t do any good, cdr will return nil before car does.
You need a base case where you find you’re done and return something instead of recursing. Right now you don’t have that. Look at examples of simple recursive functions and see how they have a base case.
To count the elements in a list there are two cases:
The base case where the list is empty (return 0)
The recursive case where the list isn’t empty (return 1 + the count of the cdr of the passed in list)
So I have my sample code down below:
(defvar answer 0)
(defvar response "")
(defun question ()
(write-line "Enter your question")
(setq response (read-line))
(if (eql (subseq response 0 2) 'Is)
(print "T")
(print "nil")
))
The basic premise is to identify if the question asked begins with the word is.
The line that I think is giving me problems is (if (eql (subseq response 0 2) 'Is). I have other programs that use eql, but for some reason this use is always returning false no matter the input. I have already spent 3 hours trying a few different variations of this code, but none have worked. Any help would be much appreciated.
What you probably want is
(string-equal (subseq response 0 2) 'Is)
string-equal compares strings ignoring the character case. Unlike string-equal the string= function compares strings accounting for character case. An equivalent using string= function would be
(string= (string-upcase (subseq response 0 2)) 'Is)
Contrary to string comparison predicates the eql predicate compares lisp objects. For equal constant strings in compiled code it is likely to return true while in your case where one object is quoted literal and another object is computed character string it would fail.
For example (eql 'is 'is) returns true while (eql "is" "is") is false in interpreted code.
I don't get why
(setq a_sym 'abc)
(print (eq a_sym 'abc))
(print (eq 'x 'x))
(print (eq (first '('x 2 3)) 'x))
prints
T
T
NIL
Why the symbol 'x in the third statement is handled differently than second ? And, down to earth, how to compare them for identity ?
If you trace what you are comparing, you will see your mistake right away:
[1]> (eq (first '('x 2 3)) 'x)
NIL
[2]> (trace eq)
** - Continuable Error
TRACE(EQ): #<PACKAGE COMMON-LISP> is locked
If you continue (by typing 'continue'): Ignore the lock and proceed
The following restarts are also available:
ABORT :R1 Abort main loop
Break 1 [3]> :c
WARNING: TRACE: redefining function EQ in top-level, was defined in C
;; Tracing function EQ.
(EQ)
[4]> (eq (first '('x 2 3)) 'x)
1. Trace: (EQ ''X 'X) ; <======= note 1
1. Trace: EQ ==> NIL
NIL
[5]> (eq (first '(x 2 3)) 'x)
1. Trace: (EQ 'X 'X) ; <======= note 2
1. Trace: EQ ==> T
T
IOW, you are "overquoting" your x: when you type 'x, it's the same as (quote x) so, you are checking for equality of symbol x and list (quote x) and, of course, getting nil.
Notes:
(eq ''x 'x): since eq is a function, its arguments are evaluated and we are comparing 'x == (quote x) with x and getting nil.
(eq 'x 'x): for the same reason, we are comparing x with x and getting t.
Related:
Lisp quote work internally
Confused by Lisp Quoting
When to use 'quote in Lisp
Lisp: quoting a list of symbols' values
Syntax and reading
You wrote:
symbol 'x
Note that 'x is not a symbol. It's a quote character in front of a symbol. The quote character has a special meaning in s-expressions: read the next item and enclose it in (quote ...).
Thus 'x is really the list (quote x).
CL-USER 9 > (read-from-string "'x")
(QUOTE X)
2
Evaluation
A quoted object is not evaluated. The quote is a special operator, which means it is built-in syntax/semantics in Common Lisp and not a function and not a macro. The evaluator returns the quoted object as such:
CL-USER 10 > (quote x)
X
Your example
(eq (first (quote ((quote x) 2 3))) (quote x))
Let's evaluate the first part:
CL-USER 13 > (first (quote ((quote x) 2 3)))
(QUOTE X)
The result is the list (quote x).
Let's evaluate the second part:
CL-USER 14 > 'x
X
So the result is the symbol x.
x and (quote x) are not eq.
Evaluation and Quoting
'('x 2 3)
What would be the purpose of the second quote in the list?
The first quote already means that the WHOLE following data structure is not to be evaluated. Thus it is not necessary to quote a symbol inside to prevent its evaluation. If a list is quoted, none of its sublists or subelements are evaluated.
Summary
The quote is not part of the symbol. It is a built-in special operator used to prevent evaluation.
How does lisp quote work internally?
For example:
(quote (+ 1 (* 1 2)) )
seems to be equivalent to
(list '+ 1 (list '* 1 2))
which means it is some how symbolizing the Head values recursively. Is this function a built in?
Run (equal (quote (+ 1 (* 1 2))) (list '+ 1 (list '* 1 2))) if you don't believe me.
How does it work?
quote is really really simple to implement. It does mostly nothing. The quote special operator just returns the enclosed object like it is. Nothing more. No evaluation. The object is not changed in any way.
Evaluation of quoted forms
Probably a good time to read McCarthy, from 1960:
Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I
Pages 16/17 explain evaluation with eval. Here:
eq [car [e]; QUOTE] → cadr [e];
or in s-expression notation:
(cond
...
((eq (car e) 'quote)
(cadr e))
...)
Above code implements the evaluation rule for QUOTE: If the expression is a list and the first element of the list is the symbol QUOTE, then return the second element of the list.
Equivalence of a quoted list with a list created by LIST
(equal (quote (+ 1 (* 1 2)))
(list '+ 1 (list '* 1 2)))
The result is T. This means that both result lists are structurally equivalent.
(eq (quote (+ 1 (* 1 2)))
(list '+ 1 (list '* 1 2)))
The result is NIL. This means that the first cons cell of the linked lists are not the same objects. EQ tests whether we really have the same cons cell object.
QUOTE returns a literal data object. The consequences of modifying this object is undefined. So, don't do it.
LIST returns a new freshly consed list each time it is called. The fresh new list will not share any cons cells with any earlier allocated list.
So the main difference is that QUOTE is a built-in operator, which returns literal and unevaluated data. Whereas LIST is a function which creates a new,fresh list with its arguments as contents.
See the effects with respect to EQ and EQUAL:
CL-USER 6 >
(flet ((foo () (quote (+ 1 (* 1 2))))
(bar () (list '+ 1 (list '* 1 2))))
(list (list :eq-foo-foo (eq (foo) (foo)))
(list :eq-foo-bar (eq (foo) (bar)))
(list :eq-bar-bar (eq (foo) (bar)))
(list :equal-foo-foo (equal (foo) (foo)))
(list :equal-foo-bar (equal (foo) (bar)))
(list :equal-bar-bar (equal (foo) (bar)))))
((:EQ-FOO-FOO T)
(:EQ-FOO-BAR NIL)
(:EQ-BAR-BAR NIL)
(:EQUAL-FOO-FOO T)
(:EQUAL-FOO-BAR T)
(:EQUAL-BAR-BAR T))
is quote a function?
quote can't be a function, since it returns its enclosed data unevaluated. Thus it is a special evaluation rule.
If quote were a function, it's arguments were evaluated. But that's exactly what is NOT what quote is supposed to do.
why does Lisp need QUOTE?
Lisp usually uses s-expressions to write Lisp code. So s-expressions have a both purpose to denote data and we use it to write programs. In a Lisp program lists are used for function calls, macro forms and special forms. symbols are used as variables:
(+ n 42)
Here (+ n 42) is a list and n is a symbol. But we also want to use lists as data in our programs and we want to use symbols as data. Thus we have to quote them, so that Lisp will not see them as programs, but as data:
(append '(+ n) '(42)) evaluates to (+ n 42)
Thus in a Lisp program, lists and variables are by default part of the language elements, for example as function calls and variables. If we want to use lists and symbols as literal data, we have to quote them, to prevent the evaluator treating them as Lisp code to evaluate.
quote does nothing more than return its argument unevaluated. But what is an unevaluated argument?
When a Lisp program is defined, it is either read from textual source into s-expression form or constructed directly in terms of s-expressions. A macro would be an example of generating s-expressions. Either way there is a data structure comprising (mostly) symbols and conses that represents the program.
Most Lisp expressions will call upon evaluation and compilation machinery to interpret this data structure as terms in a program. quote is treated specially and passed these uninterpreted symbols and conses as its argument. In short, quote does almost nothing - the value it returns already exists and is simply passed through.
You can observe the difference between passing through and fresh construction by using eq to test the identity of the return value of quote:
(defun f () '(1 2))
(defun g () (list 1 2))
(eq (f) (f)) => T
(eq (g) (g)) => NIL
As you can see, quote returns the same conses each time through.