This question arose when reading SICP. Why (list 'quote '(a b c)) evaluated by the interpreter (R5RS in Dr.Racket) as '(a b c). For me it should be (quote (a b c)). For instance (list 'quot '(a b c)) is evaluated as (quot (a b c)). What is so special in the 'quote?
You'll get different behaviors depending on exactly what Lisp you're using (Scheme, Racket, Common Lisp, etc.) but in general, the system will accept 'x as a shorthand or syntactic sugar for (quote x). The two forms are exactly equivalent and their values are the same: the unevaluated x. When a result is coming out of the system, it might choose to print in the first way to make the result more intuitive to the user. A similar thing happens with cons, too. For instance,
(cons 1 2)
;=> (1 . 2)
because that's the general way that cons cells (pairs) are printed. However, there's a special case defined for when the second part of the pair is another list (either the empty list () or another pair, and that's why we have the following. I've also written a bit more about how lists and cons cells are printed in an answer to Recursive range in Lisp adds a period?.
(cons 1 '())
;=> (1)
(cons 1 '(2 3))
;=> (1 2 3)
Now, I've written the values of the expression above. E.g., the value of the form (cons 1 '(2 3)) is the list (1 2 3). As an additional complication, some systems (I'm thinking of some languages is Dr. Racket, in particular) don't print the value of a form in the interactive prompt, but rather print a form that would produce the same (for certain interpretations of “the same”) values. For instance, you might evaluate '(1 . 2) and see the output (cons 1 2) because that's another form that would produce the same value. This can be helpful if you're doing pure functional programming that has referential transparency, but if you're not expecting it, it can lead to some confusion.
A good way to see that we're getting the results that we should, regardless of how the system prints them, is to inspect them. We expect that (list 'quote '(a b c)) should return a list whose car is the symbol quote and whose cadr is the list (a b c). This is what we get (in Dr. Racket 5.3 with language R5RS):
> (display (list 'quote '(a b c)))
'(a b c)
> (display (car (list 'quote '(a b c))))
quote
> (display (cadr (list 'quote '(a b c))))
(a b c)
We get similar results if we use 'qmmmt instead of 'quote:
> (display (list 'qmmmt '(a b c)))
(qmmmt (a b c))
> (display (car (list 'qmmmt '(a b c))))
qmmmt
> (display (cadr (list 'qmmmt '(a b c))))
(a b c)
The only difference is that in the first case, display displays the list whose car is the symbol quote using the shorthand that is available for such lists. That is, instead of displaying (quote (a b c)) it displayed '(a b c).
'(a b c) and (quote (a b c)) are actually different notations for the same. So don't be surprised if your Lisp prints the shorter version.
In general '<something> is the same as (quote <something>).
QUOTE is used in Lisp to mark expressions which should evaluate to themselves. Usually a list would be a function or macro call and a symbol would be a variable. If you want to treat those as data, you need to quote them.
Since (quote <something>) is used so often in Lisp, the abbreviated version '<something> has been introduced to save a bit of typing or reading...
display emits some behaviors. Eg. '(a . (b . (c . ()))) is displayed (a b c). 'quote is displayed quote and perhaps '(quote x y) is displayed (quote x y) while '(quote x) is displayed 'x or (quote x). Which one is implementation dependent but both mean the same.
As data (ie. quoted, like (quote quote) and it's abbrivation 'quote) the result of the evaluation, the symbol quote is nothing special, for any LISP, just like '+ and 'potato happen to be the symbols + and potato. Any symbol that mean something when not quoted is no special when quoted.
It also took me a while to understand this problem. But it's just your good-hearted lisp interpreter showing (quote (a b c)) in it's equivalent form '(a b c). Since there is no such equivalence/syntactic sugar for (quott (a b c)), it's shown as is.
Related
I making this function.
(f 3 4) (sum = 7)
(f 'a 'b) (not num!)
My problem is how can I make if condition using and operator.
I try....
(IF (and (typep a 'integer) (typep b 'integer)) (1) (0))
(IF (and ((typep a 'integer)) ((typep b 'integer))) (1) (0))
(IF ((and ((typep a 'integer)) ((typep b 'integer)))) (1) (0))
But it doesn't work.
(1) (0) is I set it temporarily.
Could I get some lisp syntax help?
The most important thing you need to learn about Lisp at this moment is that parens matter.
In C you can write 1+3, (1)+3, (((1+3))) and they all mean the same thing. In lisp they are very very different:
a means "the value of the variable named a".
(a) means "the return value of the function named a called without any arguments".
((a)) is a syntax error (but see PPS)
So, every version with ((...)) is outright wrong.
Since there is no function named 1, the first version is no good either.
What you need is:
(if (and (typep a 'integer)
(typep b 'integer))
1
0)
Note formatting and indentation.
Lispers read code by indentation, not parens, so proper indentation is critical.
Note that Emacs (and maybe some other Lisp-specific IDEs) will indent lisp code for you.
PS. The description of what you are trying to accomplish is unclear, but it might be that the easiest way is to use generic functions:
(defgeneric f (a b)
(:method ((a integer) (b integer))
(+ a b)))
(f 1 2)
==> 3
(f 1 'a)
*** - NO-APPLICABLE-METHOD: When calling #<STANDARD-GENERIC-FUNCTION F> with
arguments (1 A), no method is applicable.
PPS. Eventually you will see legitimate ((...) ...), e.g., cond:
(defun foo (a)
(cond ((= a 1) "one")
((= a 2) "two")
(t "many")))
(foo 1)
==> "one"
(foo 3)
==> "many"
or lambda forms:
((lambda (x) (+ x 4)) 5)
==> 9
but you do not need to worry about those yet.
I'm trying to create a special folding function.
I have a problem regarding quotes, Especially them nested ones. It seems like they are sometimes interpeted as the start of a list, And sometimes as a quote.
Say i've got the next code:
'(x '(a b c))
Then:
(car '(x '(a b c)))
Will return: x. While:
(cadr '(x '(a b c)))
Will return: '(a b c).
What does this mean? Is this a list? if so why does:
(caadr '(x '(a b c)))
Returns: quote. What is the meanning of this quote?
Is there any way to indentify those kind of lists? And if so, Is there any way to unquote them?
When we're evaluating a quoted expression, remember that this expression: 'x is just shorthand for this: (quote x). For example:
'(x '(a b c))
Is equivalent to:
(quote (x (quote (a b c))))
Now this expression will also return a quoted expression, which happens to start with yet another quoted expression:
(cadr (quote (x (quote (a b c)))))
---------------
=> ''(a b c)
This is more apparent in the next example, where we end up retrieving the 'quote symbol itself:
(caadr (quote (x (quote (a b c)))))
-----
=> 'quote
For the last part of the question: if you want to interpret the innermost list as a list and not as a quoted expression, then don't quote it at all:
(cadr '(x (a b c)))
=> '(a b c)
Of course, we could also leave the second quote and eval the innermost list, but that's a hassle and potentially evil:
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(eval (cadr '(x '(a b c))) ns)
=> '(a b c)
Or we could use quasiquoting and unquoting:
(cadr `(x ,'(a b c)))
=> '(a b c)
Are these 2 expressions using quotation and list the same when evaluating the expression such as a derivative?
The intrepreter outputs the same values for both:
(define a '(+ 3 4))
(define b (list '+ 3 4))
a
b
(car a)
(car b)
Output:
=> (+ 3 4)
=> (+ 3 4)
+
+
For these expressions:
(define a '(+ 3 4))
(define b (list '+ 3 4))
Do they have the same value? yes:
(equal? a b)
=> #t
Do they refer to the same object? no:
(eq? a b)
=> #f
I guess that you want to somehow process the lists (say, for calculating a derivative). It doesn't matter how you created the lists as long as you're only interested in treating them as lists of symbols, and you can safely switch back and forth between either representation. It'd be different if you were to treat the operators as actual procedures, these are different things:
(define a '(+ 3 4))
(define b (list + 3 4)) ; quote was removed
(equal? a b)
=> #f
Consider this example:
(define a '(+ 3 4))
(define b (list '+ 3 4))
(define c '(+ 3 4))
Here a will point to an immutable* list (+ 3 4). b will point to a list whose elements are the same as a but it's produced when that statement is evaluated (a can exist before the program runs since it's a constant and for a compiled program the order and how it gets produced is not important). In b you are guaranteed that all the cons cells are newly created and unique. Thus (equal? a b) ; ==>#t while (eq? a b) ; ==> #f.
The output of (eq? a c) is undefined. Some Scheme implementations will create a new immutable list while others will point to the same list created earlier because they are both immutable according to the spec.
*Immutable by the specifications in the Scheme standard but this is seldom enforced so many implementations lets you alter immutable data with undefined behavior as consequence.
I'm currently going through exercise 1.3 of the sicp book. Here's the description of the problem:
Define a procedure that takes three numbers as arguments and returns
the sum of the squares of the two larger numbers.
I tried to solve it with the following code
(define (square x) (* x x))
(define (sq2largest a b c)
((define large1 (if (> a b) a b))
(define small (if (= large1 a) b a))
(define large2 (if (> c small) c small))
(+ (square large1) (square large2))))
When I ran it in mit-scheme, I got the following error:
;Can't bind name in null syntactic environment: large1
#[reserved-name-item 13]
Googling this error doesn't yield many results. Does anyone know what's wrong with my code? (I'm not familiar with Scheme)
I'll try to break down the structure of your sq2largest procedure:
The basic structure is:
(define (sq2largest a b c)
; Body)
The Body you wrote is:
((define large1 (if (> a b) a b)) ; let this be alpha
(define small (if (= large1 a) b a)) ; let this be bravo
(define large2 (if (> c small) c small)) ; let this be charlie
(+ (square large1) (square large2)) ; let this be delta) ; This parentheses encloses body
So, the Body is structured as:
(alpha bravo charlie delta)
Which translates to: "Pass bravo, charlie and delta as arguments to alpha."
Now, alpha is being told to take a bunch of arguments, but inside the namespace reserved for large1, no provision was made for any argument... i.e. scheme encounters a null syntactic environment where it cannot bind any variable.
Parentheses are significant in Scheme (and most, if not all, Lisps) because they define the scope of a procedure and enforce[1] the order of application of operations.
[1] "No ambiguity can arise, because the operator is always the leftmost element and the entire combination is delimited by the parentheses." http://mitpress.mit.edu/sicp/full-text/sicp/book/node6.html
You have too many brackets. If you took out the extra brackets around the internal defines, things should work a lot better.
I am trying to write a function that can check whether or not some input is a quotation for a syntax checker.
I have the following code:
(define is-quote-expression?
(lambda (v)
(equal? (car v) 'quote)
(is-quotation? (cdr v)))))
(define is-quotation?
(lambda (v)
(or (number? v)
(boolean? v)
(char? v)
(string? v)
(symbol? v)
(null? v)
(and (pair? v)
(is-quotation? (car v))
(is-quotation? (cdr v)))))
When I try to evaluate, I get the following:
(is-quote-expression? '1)
#f
(is-quote-expression? (cons 'quote 1))
#t
I think my TA told me that the Scheme environment replaced all "'" with "'quote", however, this does not seem to be the case. We are running Petite Chez Scheme.
What am I not seeing?
Thanks in advance.
There are a couple of problems with your code, for starters the (lambda (pair? v) part in is-quote-expression? is almost certainly a mistake (you're defining a lambda with two parameters called pair? and v).
Also, I believe you intended to call is-quotation? from is-quote-expression? only if v isn't a pair, so it doesn't make sense to ask again if (pair? v) in is-quotation?. And who said that a pair is a quotation only if both its car and cdr are quotations?
Here, I believe this is what you intended:
(define is-quote-expression?
(lambda (v)
(if (pair? v)
(equal? (car v) 'quote)
(is-quotation? v))))
(define is-quotation?
(lambda (v)
(or (number? v)
(boolean? v)
(char? v)
(string? v)
(symbol? v)
(null? v))))
I agree with Óscar's post, though, is-quote-expression? accepts a list rather than a pair and returns whether it was a quotation.
(define is-quote-expression?
(lambda (v)
(and (proper-list-of-given-length? v 2)
(equal? (car v) 'quote)
(is-quotation? (cadr v)))))
Also, your original question shows some confusion as to what quote actually does. This is what really should happen:
> (is-quote-expression? '1)
#f
> (is-quote-expression? (cons 'quote 1))
#f
> (is-quote-expression? (quote 42))
#f
> (is-quote-expression? (quote (quote 42)))
#t
Note how the built-in quote procedure simply returns what it is passed. In the case of (quote 42) it simply returns 42. But (quote (quote 42)) returns (quote 42), which is what you wish to pass to is-quote-expression?.
The behavior of quote is specified in R6RS, appendix A.3. For '1, the relevant rule is 6sqv:
(store (sf1 ...) S1[ 'sqv1 ]) → (store (sf1 ...) S1[ sqv1 ])
Time to break this down.
The "S → T" notation defines one step in evaluating a term, where "S" evaluates to "T".
Since store and the sf1 non-terminals appear the same on both the left and right sides, you don't need to understand them to understand how '1 evaluates. If you need something, think of store as "storage environment" and the sfn as pairs of names and values; (store ((x 1) (y 2)) S) means the identifier x is associated with the value 1 and y with 2 when evaluating the term S.
If you're not familiar with the S[e] notation, it refers to a term with one "hole" (an term with a [] in it) filled with e. There are two related syntax elements: terms with holes (S[]) and terms with a hole filled by a value (S[e]). Holes are a little (but only a little) like unnamed variables. One important difference is that a term is allowed only one hole. Holes are perhaps best explained by example. All of the following are S[]:
(+ [] 1 2)
(list [] 'a "foo")
(cond ((= x 0) [])
((> x 0) 1)
(else -1))
Note that a hole can only appear where a sub-term is syntactically valid; [] 2) is not a term-with-hole. S[0] would be a term with 0 substituted into the hole:
(+ 0 1 2)
(list 0 'a "foo")
(cond ((= x 0) 0)
((> x 0) 1)
(else -1))
When a value is given for a hole, the term S[] is also called a "context". This comes from one of the primary uses for terms-with-holes: to match any term containing the given value. S[e] is any term that contains e as a valid sub-term, so S[] is the context that e appears in. In short, S1['sqv1] is a stand-in for any term that contains a quote.
(+ 'foo 1 2)
(list 'bar 'a "foo")
(cond ((= x 0) 'baz)
((> x 0) 1)
(else -1))
Note the second term provides two different contexts for quote-terms: (list [] 'a "foo"), (list 'bar [] "foo"). This suggests that you shouldn't think of holes too much as just being unnamed variables.
If you're wonder why context terms and holes are used, they're an alternative to recursive definitions. Without contexts, → would have to be defined recursively over the structure of terms (Scheme's grammar defines the structure). Substitution in lambda calculus is an example of structural recursion, as are any tree-processing functions you might define in Scheme (though Scheme syntax is quite different than the syntax used to define → and lambda calculus substitution).
(define (tree-depth tree)
(if (pair? tree)
(max (tree-depth (car tree))
(tree-depth (cdr tree)))
1
) )
Next, let's examine the meaning of sqv, which is short for "self-quoting values". This is a non-terminal from the Scheme grammar, given in appendix A.2.
sqv ::= n | #t | #f
n ::= [numbers]
sqv is simply a number or boolean.
All together, the 6sqv evaluation rule means that a quoted number or boolean evaluates to the number or boolean; the quote is simply discarded.
What this signifies for your homework is that you can't tell the difference between 1 and '1 with a normal function, since sub-terms are evaluated before the function is called. You'll need a macro.
Why go through all this just to say that "'1 evaluates to 1"? Firstly, answering "why" takes more than answering "what". Also, it will hopefully help you go beyond the question, learning a little bit how to read Scheme's formal semantics, give you a taste of computational theory concepts and lead to many more questions.