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.
Related
I am new to lisp and I had a question about this LISP syntax:
(defparameter *binary-operators*
'((+ 1 +) (- 1 -) (* 2 *)
(x 2 *) (/ 2 %) (^ 3 expt)))
From what I understand, defparameter allows the binary operators variable to be reassigned but I am confused as to how the (+ 1 +), (- 1 -) ... are evaluated. I know in LISP that (+ 4 6) would result in (4 + 6) = 10 but the same logic would result in (1 + +) which does not make sense. What does the above syntax represent?
In Common Lisp,
(defparameter name initial-value)
(see the manual) introduces a new special (global) variable name with a new value, given by evaluating initial-value.
So, in the example above, the special variable *binary-operators* is assigned a list of triples, each of them constitued by a symbol, a number, and another symbol. In other words, it assigns some data to a variable, and not, as you were thinking, redefines the syntax of the language.
Guessing from the values present in the list, this seems a variable that is assigned a list of arithmetic operators, each of them with the priority, and with the equivalent Common Lisp operator/function. Maybe this is a line of some program that maps arithmetic expressions in lisp s-expressions, or something like that.
Lisp: lists and symbols are used in data and in code
This is one of the applications where code is data. In Lisp symbols and lists are data. But they are also used to write programs: the symbols then are used for variable names, function names and much more. Lists are used to write expressions in the Lisp language - these are called forms.
In a Lisp program
(+ 1 2)
is a function call of the function named + with two values.
'(+ 1 2)
or
(quote (+ 1 2))
then is data -> the list of the symbol + and the numbers 1 and 2.
Example: infix to prefix conversion
The form you used defines a mapping from a symbol denoting a mathematical function to the weight and the actual Lisp function it represents for the conversion.
See Lispology: Infix to prefix
(defparameter *binary-operators*
; operator weight Lisp function
'((+ 1 +)
(- 1 -)
(* 2 *)
(x 2 *)
(/ 2 %)
(^ 3 expt)))
We can use it to convert infix mathematical expressions to prefix Lisp expressions (see the above linked article for the code):
CL-USER 52 > (infix-prefix '(2 * 3 ^ 4))
(* 2 (EXPT 3 4))
When we change that assoc list, then the conversion will be different. Let's change the weight of the ^ operator:
CL-USER 53 > (defparameter *binary-operators*
'((+ 1 +)
(- 1 -)
(* 2 *)
(x 2 *)
(/ 2 %)
(^ 1 expt))) ; weight changed to 1
*BINARY-OPERATORS*
Now we can convert the example from above and we get a different Lisp form:
CL-USER 54 > (infix-prefix '(2 * 3 ^ 4))
(EXPT (* 2 3) 4)
So, *binary-operators* is data, which drives the conversion from infix mathematical expressions to Lisp forms. Instead of hardwiring the rules into the code, here we are using an assoc list to keep the mappings. Thus allows us to add new operators by changing the assoc list, without changing the actual code.
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.
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)
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.
Suppose I have a function
CL-USER> (defun trimmer (seq) "This trims seq and returns a list"
(cdr
(butlast seq)))
TRIMMER
CL-USER> (trimmer '(1 2 3 VAR1 VAR2))
(2 3 VAR1)
CL-USER>
Notice how, due to QUOTE, VAR1 and VAR2 are not resolved. Suppose I want to resolve the symbols VAR1 and VAR2 to their values - is there a standard function to do this?
Do not use quote to create a list with variables; use list instead:
CL-USER> (trimmer (list 1 2 3 var1 var2))
(2 3 value-of-var1)
(where value-of-var1 is the value of var1).
Quote only prevents evaluation of whatever its argument is. If its argument happens to be a list literal, then that is returned. However, to create lists that are not just literals, use list. You can use backquote syntax, but that is rather obfuscation in such a case.
Backquote is the usual way to interpolate values into a quoted list:
> (setq var1 4 var2 5)
5
> `(1 2 3 ,var1 ,var2)
(1 2 3 4 5)
Edited to add: if you want to process a list so that symbols are replaced with their symbol-value, then you need a function something like this:
(defun interpolate-symbol-values (list)
"Return a copy of LIST with symbols replaced by their symbol-value."
(loop for x in list
collect (if (symbolp x) (symbol-value x) x)))
> (interpolate-variables '(1 2 3 var1 var2))
(1 2 3 4 5)
This seems like a strange thing to want to do, however. Can you say more about what you are trying to achieve? Almost certainly there's a better way to do it than this.