I am currently studying about Lisp but I still don't get quote.
Why use quote in Lisp?
And I got a problem here which is hard to understand to me.
(car (car '((a b) c d)))
The above gives A.
But I don't know why the result is A because there is no quote first car after.
quote is an operator; its meaning only kicks in when it is the head of a Lisp expression which is evaluated. The syntax 'X stands for (quote X): the Lisp reader translates a prefix apostrophe, followed by any syntactic unit X denoting one object, into the syntax (quote X). The quote expression, when evaluated, returns the syntax X itself as the value, rather than the value of the syntax. For instance (quote (+ 1 2)) returns the three element list (+ 1 2), rather than the value of the expression (+ 1 2) which is 3. quote effectively reflects a piece of the program's list-based syntax back into the running program as a value.
In the expression:
(car (car '((a b) c d)))
we simply have a nested function application to a value:
(car (car value))
This value is the result of a quote expression, and so the value is the object ((a b) c d). This object started out as a piece of syntax wrapped inside quote, but is now a run-time value being passed to the car function. The inner car produces the first element of the list, returning (a b). This (a b) value is passed to the outer car, which retrieves the a.
Lisp provides quote because it is a homoiconic language. The principal data structures manipulated in that language have a printed notation, and that printed notation is used to write programs also. Thus programs are understood to be made out of a data structure. In this kind of language, suppose you want to be able to use any data structure as a literal. Of course, that creates confusion because the data uses the same notation as the code, and some data structures look like valid syntax. You need an operator which you can wrap around a piece of syntax to say, "this is literal data; do not evaluate this as an expression, but just the data that it looks like".
This is exactly the same like when we use English to talk about English. We have to use quotes—at least when we write this talk down. A sentence like:
A penny saved is a penny earned is a good old proverb.
is badly written. Of course we understand what it means because our brains are good at dealing with ambiguity and mistakes, but it appears to be saying that a penny is a proverb. We need quotes:
"A penny saved is a penny earned" is a good old proverb.
See? The quote says that this sentence is not a relative clause of my sentence; it's text that my sentence is talking about (which happens to be in the same language that I'm using to talk about it). This is why the Lisp operator is called quote: it's related to this type of quoting.
Why use quote
Think of the quote as an indication that it's data and not to be thought of as code:
(cons 1 2) ; ==> (1 . 2) (a cons with car as 1 and cdr as 2)
'(cons 1 2) ; ==> (cons 1 2) (a list with the symbol cons and the numbers 1 and 2)
You see in the first that is not quoted it's executed and the result is the result of the cons function. In the second you could say quote is executed and it evaluates soley to it's argument. Note that 'x is just an abbrevation for (quote x) and both thus evaluate to x while without quote it would evaluate to the value bound to the variable x.
Nested functions
When you nest functions like (car (car '((a b) c d)))) you'll se why you need to quote since all arguments in functions are evaluated. Thus before the outer car can be applied it needs to evaluate it's argument (car '((a b) c d))) and before the inner car can do it's job it needs to evaluate it's argument '((a b) c d)). We know that '((a b) c d)) becomes ((a b) c d)) and car of this is (a b). The outer car then works on (a b) and thus a is the result. If you would have put the quote like this (car '(car ((a b) c d)))) then the innser car is just a symbol in the data structure and not a function. car evaluates its argument to be (car ((a b) c d))) and car of that is the symbol car.
'((a b) c d)) ; ==> ((a b) c d))
(car '((a b) c d)) ; ==> (a b)
(car (car '((a b) c d))) ; ==> a
'(car ((a b) c d)) ; ==> (car ((a b) c d))
(car '(car ((a b) c d))) ; ==> car
Also know that if you put quotes inside quoted data, like ''x only the outer quote is taken off and the rest is data. The result is (quote x) or 'x depending on the display settings but since it's already data quote here is just a symbol. (car ''x) ; ==> quote (symbol)
Related
I would like to have a clear understanding, what is 'Atom' in LISP?
Due to lispworks, 'atom - any object that is not a cons.'.
But this definition is not enough clear for me.
For example, in the code below:
(cadr
(caddar (cddddr L)))
Is 'L' an atom? On the one hand, L is not an atom, because it is cons, because it is the list (if we are talking about object, which is associated with the symbol L).
On the other hand, if we are talking about 'L' itself (not about its content, but about the symbol 'L'), it is an atom, because it is not a cons.
I've tried to call function 'atom',
(atom L) => NIL
(atom `L) => T
but still I have no clue... Please, help!
So the final question: in the code above, 'L' is an atom, or not?
P.S. I'm asking this question due to LISP course at my university, where we have a definition of 'simple expression' - it is an expression, which is atom or function call of one or two atomic parameters. Therefore I wonder if expression (cddddr L) is simple, which depends on whether 'L' is atomic parameter or not.
Your Lisp course's private definition of "simple expression" is almost certainly rooted purely in syntax. The idea of "atomic parameter" means that it's not a compound expression. It probably has nothing to do with the run-time value!
Thus, I'm guessing, these are simple expressions:
(+ 1 2)
42
"abc"
whereas these are not:
(+ 1 (* 3 4)) ;; (* 3 4) is not an atomic parameter
(+ a b c) ;; parameters atomic, but more than two
(foo) ;; not simple: fewer than one parameter, not "one or two"
In light of the last counterexample, it would probably behoove them to revise their definition.
On the one hand, L is not an atom, because it is cons, because it is the list (if we are talking about object, which is associated with the symbol L).
You are talking here about the meaning of the code being executed, its semantics. L here stands for a value, which is a list in your tests. At runtime you can inspect values and ask about their types.
On the other hand, if we are talking about 'L' itself (not about its content, but about the symbol 'L'), it is an atom, because it is not a cons.
Here you are looking at the types of the values that make up the syntax of your code, how it is being represented before even being evaluated (or compiled). You are manipulating a tree of symbols, one of them being L. In the source code, this is a symbol. It has no meaning by itself other than being a name.
Code is data
Lisp makes it easy to represent source code using values in the language itself, and easy to manipulate fragments of code at one point to build code that is executed later. This is often called homoiconicity, thought it is somewhat a touchy word because people don't always think the definition is precise enough to be useful. Another saying is "code is data", something that most language designers and programmers will agree to be true.
Lisp code can be built at runtime as follows (> is the prompt of the REPL, what follows is the result of evaluation):
> (list 'defun 'foo (list 'l) (list 'car 'l))
(DEFUN FOO (L) (CAR L))
The resulting form happens to be valid Common Lisp code, not just a generic list of values. If you evaluate it with (eval *), you will define a function named FOO that takes the first element of some list L.
NB. In Common Lisp the asterisk * is bound in the REPL to the last value being successfully returned.
Usually you don't build code like that, the Lisp reader turns a stream of characters into such a tree. For example:
> (read-from-string "(defun foo (l) (car l))")
(DEFUN FOO (L) (CAR L))
But the reader is called also implicitly in the REPL (that's the R in the acronym).
In such a tree of symbols, L is a symbol.
Evaluation model
When you call function FOO after it has been defined, you are evaluating the body of FOO in a context where L is bound to some value. And the rule for evaluating a symbol is to lookup the value it is bound to, and return that. This is the semantics of the code, which the runtime implements for you.
If you are using a simple interpreter, maybe the symbol L is present somewhere at runtime and its binding is looked up. Usually the code is not interpreted like that, it is possible to analyze it and transform it in an efficient way, during compilation. The result of compilation probably does not manipulate symbols anymore here, it just manipulates CPU registers and memory.
In all cases, asking for the type of L at this point is by definition of the semantics just asking the type for whatever value is bound to L in the context it appears.
An atom is anything that is not a cons cell
Really, the definition of atom is no more complex than that. A value in the language that is not a cons-cell is called an atom. This encompasses numbers, strings, everything.
Sometimes you evaluate a tree of symbols that happens to be code, but then the same rule applies.
Simple expressions
P.S. I'm asking this question due to LISP course at my university, where we have a definition of 'simple expression' - it is an expression, which is atom or function call of one or two atomic parameters. Therefore I wonder if expression (cddddr L) is simple, which depends on whether 'L' is atomic parameter or not.
In that course you are writing functions that analyze code. You are given a Lisp value and must decide if it is a simple expression or not.
You are not interested in any particular interpretation of the value being given, at no point you are going to traverse the value, see a a symbol and try to resolve it to a value: you are checking if the syntax is a valid simple expression or not.
Note also that the definitions in your course might be a bit different than the one from any particular exising flavor (this is not necessarily Common Lisp, or Scheme, but a toy LISP dialect). Follow in priority the definitions from your course.
Imagine we have a predicate which tells us if an object is not a number:
(not-number-p 3) -> NIL
(not-number-p "string") -> T
(let ((foo "another string))
(not-number-p foo)) -> T
(not-number '(1 2 3)) -> T
(not-number (first '(1 2 3)) -> NIL
We can define that as:
(defun not-number-p (object)
(not (numberp object))
Above is just the opposite of NUMBERP.
NUMBERP -> T if object is a number
NOT-NUMBER-P -> NIL if object is a number
Now imagine we have a predicate NOT-CONS-P, which tells us if an object is not a CONS cell.
(not-cons-p '(1 . 2)) -> NIL
(let ((c '(1 . 2)))
(not-cons-p c)) -> NIL
(not-cons-p 3) -> T
(let ((n 4))
(not-cons-p n)) -> T
(not-cons-p NIL) -> T
(not-cons-p 'NIL) -> T
(not-cons-p 'a-symbol) -> T
(not-cons-p #\space) -> T
The function NOT-CONS-P can be defined as:
(defun not-cons-p (object)
(if (consp object)
NIL
T))
Or shorter:
(defun not-cons-p (object)
(not (consp object))
The function NOT-CONS-P is traditionally called ATOM in Lisp.
In Common Lisp every object which is not a cons cell is called an atom. The function ATOM is a predicate.
See the Common Lisp HyperSpec: Function Atom
Your question:
(cadr (caddar (cddddr L)))
Is 'L' an atom?
How would we know that? L is a variable. What is the value of L?
(let ((L 10))
(atom L)) -> T
(let ((L (cons 1 2)))
(atom L) -> NIL
(atom l) answers this question:
-> is the value of L an atom
(atom l) does not answer this question:
-> is L an atom? L is a variable and in a function call the value of L is passed to the function ATOM.
If you want to ask if the symbol L is an atom, then you need to quote the symbol:
(atom 'L) -> T
(atom (quote L)) -> T
symbols are atoms. Actually everything is an atom, with the exception of cons cells.
I am taking a programming language principle class where the professor talks about macro using Lisp (Precisly, Elisp). However, he didn't teach us how to write this language. As a result, I am trying to learn myself.
However, there are something that I just can't understand regarding the use of "tick" (') in Lisp. I do, however, understand the basic use. For example, if we have (cdr '(a b c)) it will give us a list (b c). Without the tick symbol, (a b c) would be evaluated as a function.
In the code written by my professor, I have noticed a strange use of "tick" symbol that I can't really understand the usage:
; not sure why there is a "'" in front of if and it is being added to a list ??
(defmacro myand(x y) (list 'if x y nil))
; Another example. Tick symbol before "greater than" symbol ? and made into a list?
(list 'if (list '> x y))
The uses of list and tick symbol just doesn't really make sense to me. Can anyone explain what is going on here? I suppose this is something special to Lisp
The 'tick symbol' is ': '<x> is syntactic sugar for (quote <x>) for any <x>. And (quote <x>) is simply <x> for any object <x>.
quote is needed in Lisp because programs in Lisp often want to reason about things which would have meaning as parts of Lisp programs, and need to say 'this isn't part of this program: it's data'. So, for instance, if I have a list of the form
((a . 1) (b . 2) ... (x . 26)) and I want to look up a symbol in it, I might write a function like this:
(defun ass (key alist)
(if (null? alist)
'()
(if (eql (car (car alist)) key)
(car alist)
(ass key (cdr alist)))))
Then when I wanted to look up, say x, I would have to say (ass (quote x) ...) because if I said (ass x ...) then x would be treated as a variable, and I don't want that: I want the symbol x.
In your example you are looking at programs which write Lisp programs – macros in other words – and these programs need to spend a lot of their time manipulating what will be Lisp source code as data. So in your myand macro, what you want is that
(myand x y)
should be rewritten as
(if x y nil)
Which is the same thing. So to construct this you need a list of four elements: the symbol if, the two variables and the symbol nil. Well you can make a list with list:
(list 'if x y 'nil)
Except that it turns out that the value of the symbol nil is just itself (nil is rather special in many Lisps in fact), so you can not bother quoting that: (list 'if x y nil) (I personally would have quoted it in this case, to make it clear what was literal and what was being evaluated, but that's probably not common).
I am learning about racket/scheme and came across an online resource that said, if a function written using a cond gives true or false, it can be rewritten using only not, and, and or. I have worked out some simple examples where I was able to to convert cond statements into a statement only involving not and and or. My question is if there is a way that the logic can be "seen" right away when converting between these two types of statements. I understand that it is not always practical to convert every cond statement into a combination of not's and's and or's but I am interested in learning about the logic behind the process of converting.
Thanks in advance.
(If something about the question does not make sense, leave a comment and I will try clarifying what I want to understand)
All conditional expressions (and not only those evaluating to true/false) can be rewritten using only boolean combinators. This is because of how logical operators are evaluated in Scheme/Racket. For instance, logically (and a b) would be true if both a and b are true, and otherwise false. But in Racket, the result of (and a b) is b if both a and b are truthy, and otherwise false. That is, evaluation proceeds to the right until either the last argument or a falsy value is encountered. At that point, evaluation stops and that value (which could be a boolean but needn't be) is returned. It's because and and or don't simply produce boolean output that they can be used to stand in for conditional expressions.
E.g.
(if #t 'hello 'bye) ;=> hello
(or (and #t 'hello) 'bye) ;=> hello
(if #f 'hello 'bye) ;=> bye
(or (and #f 'hello) 'bye) ;=> bye
(cond [#f 'hello]
[#f 'bye]
[#t 'aloha]) ;=> aloha
(or (and #f 'hello)
(and #f 'bye)
(and #t 'aloha)) ;=> aloha
But you wouldn't usually want to use them that way since they're hard to read. As a general guideline, use if and cond in most cases, rather than elementary boolean operators. If you only care about taking action on a positive or negative result of the conditional, then you could use when or unless. If you do care about handling both positive and negative results, but one of them is a boolean result such as this example:
(if (positive? n)
#t
(even? n))
... then this would be a case where a boolean operator would be preferable, like so:
(or (positive? n) (even? n))
If both arms of the if conditional are boolean values, like this:
(if (> n 3)
#t
#f)
... then just replace the entire conditional expression with the condition itself:
(> n 3)
Otherwise, stick to if and cond.
Once you convert a cond to nested ifs, you can always turn it into and or and not like this:
(if A B C) --> (or (and A B) (and (not A) C))
However, if you do this blindly, you will get a much more complicated expression than what you could get, so I would add a couple more transformations you can use:
(if A B #f) --> (and A B)
(if A B #t) --> (or (not A) B)
(if A #f C) --> (and (not A) C)
(if A #t C) --> (or A C)
(note: that or above might return a different truthy-value other than #t, making it technically different but equivalent-when-used-as-a-boolean)
Another thing I should note is that sometimes you can transform a multi-branch cond into and or not without transforming into ifs first. For example a 3-branch cond:
(cond [A B]
[C D]
[else E])
-->
(or (and A B)
(and (not A) C D)
(and (not A) (not C) E))
Or a 4-branch cond:
(cond [A B]
[C D]
[E F]
[else G])
-->
(or (and A B)
(and (not A) C D)
(and (not A) (not C) E F)
(and (not A) (not C) (not E) G))
Each and corresponds to a cond-branch, and each cond-branch's and has nots in it for every previous condition, in addition to its own condition.
A more generic rule you can apply:
for i from 1 through n,
(cond [Q_i A_i]
...
[else E])
-->
on each i, for j from 1 through i-1,
(or (and (not Q_j) ... Q_i A_i)
...
(and (not Q_i) ... E)
First of all, you need to desugar cond language into a sequence of if-then-else sequences, which is trivial.
After that, you can rewrite if conditionals into boolean operators. You can look into a manual of propositional logic to learn this. Or look here.
Btw. It is forbidden to paste your homework on stack overflow.
Racket has only foldl and foldr, which require initial value. Haskell in addition has foldl1 and foldr1, which instead of applying a function on the initial value and the first element, applies to first and second element. Currently i implemented them as:
(define (foldl1 f xs)
(foldl f (first xs) (rest xs)))
Is there a better way?
There is a better way, just (require srfi/1) and use reduce and reduce-right. :-D
What you are describing looks like reduce in CL. Your procedure looks ok except it would fail if the list is empty.
Be aware that first and rest are not the same as car and cdr since they only work on proper lists. eg.
(first '(a b c d e . f))
;;==>
;;first: contract violation
;; expected: (and/c list? (not/c empty?))
;; given: '(a b c d e . f)
Now. For racket to signal here it must have traversed the whole list to make sure it ends with null and since it didn't it signaled an error. I did a small test and found out that sorting a 2 million list used 32% more time with first/rest.
What's the difference between:
(cons 'a (cons 'b 'c)) ;; (A B . C)
and
(cons 'a '(b.c)) ;; (A B.C)
I need to create the following list ((a.b).c) using cons so i'm trying to understand what that "." represents.
L.E.: I have the following (cons (cons 'a 'b) 'c) but it produces ((A . B) . C) and not ((A.B).C) (Note the extra spaces)
Spaces are used to separate list tokens. A.B is a single token. (A.B) is a list with a single element. (A . B) is a cons cell with A as car and B as cdr.
A cons cell is a pair of "things" (objects). In your case, these things are symbols, and they are named A, B, etc.. The printed representation of such a cell is (A . B), for example. This is called "dot notation". The first element is called "car", the second "cdr".
The function cons creates such a cell. (cons 'a 'b) thus produces the cell (A . B). Note that names are always upcased internally.
This is most likely what your teacher wanted, so ((A . B) . C) is the correct output, and your code the right answer. This is a cell where the car points to another cell, and the cdr contains C. That other cell is a cell where the car contains A and the cdr B.
By the way, a list is a linear chain of such cons cells, such that the car always holds a value and the cdr points to the rest of the list. The last cdr points nowhere (which is called NIL in Lisp). In dot notation, a list is e.g. (A . (B . (C . NIL))). Since lists are important, they can be written shorter like this: (A B C). If the last CDR has a value instead of NIL, it is shown in dot notation, e.g. (A . (B . (C . D)))) can be written as (A B C . D).
. between two characters is a part of a symbol. b.c is a symbol with a name of three characters: b, ., and c.
If you enter FOO.BAR, then Lisp will read it as one symbol.
If you enter (FOO.BAR) then Lisp will read it as a list with one symbol as its contents.
If you enter (FOO . BAR) then Lisp will read it as a cons cell with FOO as the CAR and BAR as the CDR.
. is used to separate the CAR and the CDR of a cons cell: (a . b). Note the space around ..
(cons 'b 'c) creates a cons cell with the symbol b as the CAR and the symbol c as the CDR. It is written as (b . c).
(cons 'a '(b.c)) creates a list of two symbols, a and b.c. It is written as (a b.c).
((A.B).C) is always printed as ((A.B) . C). It is also not a list.
((a.b) . c) is a cons cell with the list (a.b) as the CAR and the symbol c as the CDR.
If this is in the course of learning lisp, the question probably did not meant an implied "no space allowed" rule, as spaces are not significant against parenthesis, and the correct answer is the one you gave.
In particular, the space after a closing parenthesis is always added, but it's for human readability purpose only. It does not make any sense to require it not to be printed.