Domanda

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.

È stato utile?

Soluzione

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?.

Altri suggerimenti

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))))

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top