Lisp: Evaluation of quotes - lisp

Which of the following expressions has correct lisp syntax?
(+ 1 (quote 1))
==> 1 (???)
(+ 1 (eval (quote 1))
==> 2
I'm currently writing my own lisp interpreter and not quite sure how to handle the quotes correct. Most lisp interpreters I've had a look at evaluate both expressions to "2". But shouldn't the quote be not evaluated at all and thereby only the second one be a legal expression? Why does it work then anyway? Is this some kind of syntactical sugar?

Barring special forms, most Lisps evaluate the arguments first, then apply the function (hence the eval-and-apply phrase).
Your first form (+ 1 '1) would first evaluate its arguments 1 and '1. Constant numerics evaluate to themselves, and the quote evaluates to what it quotes, so you'd be left applying + to 1 and 1, yielding 2.
eval: (+ 1 (quote 1))
eval 1st arg: 1 ==> 1
eval 2nd arg: '1 ==> 1
apply: (+ 1 1) ==> 2
The second form is similar, the unquoted 1 will just go through eval once, yielding 1 again:
eval: (+ 1 (eval '1))
eval 1st arg: 1 ==> 1
eval 2nd arg: (eval '1)
eval arg: '1 ==> 1
apply: (eval 1) ==> 1
apply: (+ 1 1) ==> 2

Numbers evaluate to themselves so (quote 1) is the same as 1.

Related

Macro Issues: Eval of a macro body works, but the macro doesn't

Consider the following code snippet:
[1]> (defvar *clist* '((2 1 21) ( 3 2 32) (4 3 43)))
*CLIST*
[2]> (eval `(case '1 ,#(mapcar #'rest *clist*)))
21
[3]> (defmacro tester (index clist)
`(case ,index ,#(mapcar #'rest clist)))
TESTER
[4]> (tester '1 *clist*)
*** - MAPCAR: A proper list must not end with *CLIST*
The following restarts are available:
ABORT :R1 Abort main loop
Break 1 [5]>
The code contains the error-message generated.
As one can clearly see, that eval of the code that is used as the body
of the macro tester , gives a result. But the same code (by replacing
*clist* and '1, by clist and index variables.) doesn't work when it's used as a body of the macro.
When testing backquote, just print it:
> `(case '1 ,#(mapcar #'rest *clist*))
(CASE '1 (1 21) (2 32) (3 43))
When testing macros, you do not evaluate them (either at REPL or, all
the more so, using eval
explicitly).
You expand the macro using macroexpand
and examine the code.
E.g.,
> (macroexpand-1 '(tester '1 *clist*))
*** - MAPCAR: A proper list must not end with *CLIST*
This tells you that tester passes the symbol *CLIST* instead of
its value to mapcar.
You need to think what you are trying to do in terms of
"compile-time"
vs "execution time".
Do you know the index at compile time?
Do you know the clist at compile time?
In your case, there is no reason to use case:
(defmacro tester (index clist) `(third (find ,index ,clist :key #'second)))
(macroexpand-1 '(tester 1 *clist*))
==> (THIRD (FIND 1 *CLIST* :KEY #'SECOND)) ; T
(tester 1 *clist*)
==> 21
Since you do not know the value of clist at compile time (only the
variable name where it is stored), there is
no win in using case - it has to know all clauses at compile time.
Let's take your macro, remove the expansion and just print its arguments:
CL-USER 4 > (defmacro tester (index clist)
(print (list :macro-tester :index index :clist clist))
nil)
TESTER
Now we call it with your example:
CL-USER 5 > (tester 1 *clist*)
(:MACRO-TESTER :INDEX 1 :CLIST *CLIST*)
NIL
So index is 1 and clist is the symbol *clist*.
Now let's try to call mapcar with the function rest and the symbol *clist*:
CL-USER 9 > (mapcar #'rest '*clist*)
Error: *CLIST* (of type SYMBOL) is not of type LIST.
1 (abort) Return to level 0.
2 Return to top loop level 0.
That's the error you are seeing. The symbol *clist* is not a valid list.

Apparent 'eval' of quote symbol in CLISP

Some output from the CLISP REPL:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
The first three, I understand exactly what's going on: The list function is passed a symbol ('list or 'quote) and so the result is a list that begins with the list or quote symbol. It's the fourth that confuses me. Why doesn't it return (QUOTE (1 2 3))?
I realise that if you enter (QUOTE '(1 2 3)) into the REPL, you get '(1 2 3) back, so the expression are equivalent in that sense. But (LIST 1 2 3) is equivalent to (1 2 3), and yet the first expression doesn't return that.
It seems inconsitent that (list 'quote 1 2 3) returns a list with the first item being a quote symbol, but (list 'quote (1 2 3)) returns a quoted list. Especially since expressions like (list 'list ...) seem to always return a list beginning with the symbol - so far, at least, quote is the only 'special case' like this.
It's not the easiest question to articulate, so I'm hoping I've managed to get my confusion across. Can anyone explain why quote gets treated in this seemingly-unique way?
'something is the same as (quote something) for the lisp reader. Even when nested it will be the case. The next expressions I will double quote so that after evaluation one of the quotes are still in there.
When printing the implementations can choose what to output where there are several possible representations, so some implementations would print the evaluation of ''something as
(quote something) while others may use the abbreviation 'something.
'(quote 1 2 3) cannot be abbreviated since a quoted form only has one argument. Thus here both lisp systems would print (quote 1 2 3).
Here is a way to look at your last expression:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
This will either evaluate to "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)" or "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)".
Since the printer never sees if the input is abbreviated and the data has the same structure in memory the output is never affected by how you input the data. Thus (quote (quote (1 2 3))) will print the same as ''(1 2 3).
You have the same behaviour with cons cells but the standard dictates how the rules are. (cons 1 (cons 2 (cons 3 '()))) would be (1 . (2 . (3 . ()))) but is actually just printed (1 2 3) However if you (cons 1 2) you get (1 . 2) showing that print treats the output differently based on the cdr. However the reader can read any of these and they will all print the same eg. '(1 . (2 . (3 . ()))) ==> (1 2 3) and (+ . (2 . ( 3 . ()))) ; ==> 5
Numbers can have as many visual forms as there are bases below the number in question.
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list does not have any abbreviation or specialness in Lisp. It's not even a primitive function but it's very helpful as it removes the inconvenience of having to cons by hand everytime. It can be defined like this:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)
Note that a REPL (the READ-EVAL-PRINT-LOOP) does three things:
reading using the function READ
evaluating using the function EVAL
and printing the result using something like the function PRINT
To understand what is going on you have to look at all three functions.
Let's look at the third form:
(list 'quote 1 2 3)
This is read as a list of five elements:
LIST
(QUOTE QUOTE)
1
2
3
EVAL then evaluates the arguments, and calls the function list with the four results and returns a new result, a list of four elements:
QUOTE
1
2
3
PRINT then takes this list and writes it as: (QUOTE 1 2 3). There is no abbreviated way to print it.
Let's look at the fourth form:
(list 'quote '(1 2 3))
This is read as a list of three elements:
LIST
(QUOTE QUOTE)
(QUOTE (1 2 3))
eval calls list with two arguments:
QUOTE
(1 2 3)
eval then returns a list of length two:
QUOTE
(1 2 3)
print now can print this list in two different ways:
(QUOTE (1 2 3)) or the abbreviated form '(1 2 3). Here a quote character is in front of a single expression.
Your implementation used the first version.

quoting choices based on ~ and ~# in Clojure macro

I have two different Clojure macros, but based on the operation (~# and ~), I need to quote the input or not.
(defmacro make2 [t]
`(list 1 ~#t))
(defmacro make3 [t]
`(list 1 ~t))
(make2 (1 2 3)) -> (1 1 2 3)
(make3 '(1 2 3)) -> (1 (1 2 3))
Why is this? I can guess that with macro, the arguments are not evaluated (that's the reason why make2 doesn't cause an error). However after getting the arguments, I'm not sure the logic to process them.
(macroexpand-1 '(make2 (1 2 3)))
;; ==> (clojure.core/list 1 1 2 3)
(macroexpand-1 '(make3 (1 2 3)))
;;==> (clojure.core/list 1 (1 2 3))
~# splices the list (1 2 3) into the expression (list 1 ...) and then evaluates the resulting expression, i.e. evaluates the function list with the arguments 1 1 2 3. Clojure evaluates each argument, but numbers evaluate to themselves, of course.
~ just inserts the argument (1 2 3) into (list 1 ...) as its second argument and then evaluates the entire expression, evaluating each argument to list as well. When it does, Clojure sees that there is an unquoted pair of parentheses in the second argument, and assumes that the first expression after that left parenthesis is a function (or macro). That is, Clojure assumes that the inner instance of 1 is a function, which it's not. That's why you get the exception
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn ...
which says that a Long integer cannot be transformed into a function.

lisp program to calculate the sum of n numbers

(defun sum-n-numbers(n)(if(=n 1)
1
(+N(sum-n-numbers(-n 1)))))
Edit 2:(defun sum-n-numbers(n)
(if(=n 1)
1
(+N(sum-n-numbers(-n 1))
)
)
)
The above code runs but when I type (SUM-N-NUMBERS 1 3 2) for the output,it does not work and I get errors.
I know this simple code can also be executed by the inbuild lisp function (+ 1 3 2) that automatically calculates the sum of the numbers,but I have an exam question where it is asked to calculate the sum of n numbers using the defun function.
Edit 1: This is the error that I am getting:
Error: Call ((LAMBDA (#:N) (DECLARE (SPECIAL:SOURCE #) (LAMBDA-NAME SUM-N-NUMBERS)) (BLOCK #:SUM-N-NUMBERS (IF # 1 #))) 1 3 2) has the wrong number of arguments.
1 (abort) Return to level 1.
2 Return to debug level 1.
3 Return to level 0.
4 Return to top loop level 0.
What's wrong with:
(apply '+ '(1 3 2))
??
(defun sum (numbers)
(if (null numbers)
0
(+ (first numbers) (sum (rest numbers)))))
(sum '(1 3 2))
Didn't test. I don't have a lisp interpreter at hand.
To get exactly what you want:
(defun sum-n-numbers (&rest nums)
(if (null nums) 0
(+ (car nums) (apply #'my-sum (cdr nums)))))
This will take an arbitrary number of arguments and recursively compute their sum. For instance:
(sum-n-numbers 1 2 3) => 6
Using iteration, not recursion:
(defun sum-n-numbers (&rest nums)
(loop for num in nums summing num))
From the user's point of view, these are the same, just a little bit different in how they work inside. And I've tested both of these to ensure they work.
The function you wrote accepts one argument and returns the sum of of numbers from 1 to the argument (note that it will never return - theoretically - and fail with a stack overflow - in practice - for negative arguments).
That function cannot accept 3 arguments you passed to it, so you got an error.

List Item Evaluation

I'm learning lisp and have a question about a simple list:
(setq stuff '(one two three (+ 2 2)))
stuff ; prints "one two three (+ 2 2)"
(setq stuff (list `one `two `three (+ 2 2)))
stuff ; prints "one two three 4"
The first setq creates a list "one two three (+ 2 2)". The second list creates "one two three 4". Why does the first list not evaluate the (+ 2 2), but the second one does? I read in the Emacs Lisp intro documentation that when the list is built that it evaluates from the inside out. Why doesn't the first list evaluate the addition before adding it to the list?
This is elisp in emacs 24.
' is not equivalent to list, it's shorthand for quote. You're really doing this:
(setq stuff (quote (one two three (+ 2 2))))
The argument to quote is the expression (one two three (+ 2 2)).
From http://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html: "The special form quote returns its single argument, as written, without evaluating it".
Looks like you're coming to grips with the evaluation semantics of Lisp, so keep playing around!
You can think of quote as suppressing evaluation of its argument. This allows you to write expressions that you can manipulate or pass around. It is also used to write data structures that should not be evaluated as function calls.
Data structures:
'(1 2 3) ; => '(1 2 3)
(1 2 3) ; => Lisp error: (invalid-function 1)
;; The Lisp reader sees the number 1 in the function position and tries to call it, signalling an error.
Syntax transformations:
(setq x '(string-to-int "123"))
(setf (car x) 'string-to-list)
x ; => '(string-to-list "123")
Delayed evaluation:
(setq x '(message "Hello World")) ; => '(message "Hello World")
(eval x) ; => "Hello World"
There is a closely related special operator called syntax quote, written using the backtick. It allows you to evaluate individual forms in a quoted expression using the comma ( , ) operator. It is like quote with an escape hatch.
`(1 2 (+ 3 4)) ; => '(1 2 (+ 3 4))
`(1 2 ,(+ 3 4)) ; => '(1 2 7) ;; Note the comma!
Syntax quote also permits list splicing using the ,# syntax:
`(1 2 ,#(+ 3 4)) ; => '(1 2 + 3 4)
As you can see, it splices the subsequent expression into the containing one. You probably won't see it all that often until you start writing macros.
list on the other hand is a simple function. It evaluates its arguments, then returns a new data structure containing these items.
(list 1 2 (+ 3 4)) ; => '(1 2 7)